<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
                      "http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
  <title>SIT Programming Manual</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <link rel="stylesheet" title="default" type="text/css" href="default.css">
  <script type="text/javascript" src="toc.js"></script>
</head>
<body onload="toc.build()">

<div id="doc">
<div id="bg">
<h1>SIT Programming Manual</h1>

<p id="tagline">Simple Interface Toolkit</p>

<div class="sep"></div>
<div id="toc"></div>

<p id="auth">Written by T.Pierron, April 2010</p>

<h2><span class="num">I.</span> Introduction</h2>

<p><span class="lettrine">W</span>elcome to SIT programmer's manual, a comprehensive
guide through the Simple Interface Toolkit: a simple framework to build graphical
user interface for Microsoft Windows operating system (Windows 2000 or later). To
understand this guide, you will need a pretty good knowledge of the C programming
language, in its flavour ISO C90 at least, or preferably C99, including the
compilation tool chain. If you just started learning this language and barely
make the difference between pointers, arrays and static strings, or if you don't
know what's the purpose of the compilation phases (pre-processing, compiling,
assembly, linking), it is strongly advised to complete your course before digging in
this <acronym title="Application Programming Interface">API</acronym>. The good news
is, you won't have to know most of Microsoft <acronym title="Software Development Kit">SDK</acronym>
specificities, and the few that have to be known will be explained in this
<a href="#chapter16">document</a>.</p>

<p>The main motivation for this library came after realizing the poor state of
framework using plain ANSI C, and even to some extend C++. You cannot have
something lightweight and simple to use. It seems to have some preconceived
ideas, that C is a poor choice for such kind of task, somewhat reinforced by
the huge number of attempts that failed to meet both targets.</p>

<p>This framework is a sort of proof of concept, that, indeed, you can have both.
Its main source of inspiration came from <em>X Intrinsics</em> and <em>Motif (Xm)</em>.
Although very few people nowadays know their existance, it is still a shame that very
few got inspired by the way they work, because they had a pretty smooth
learning curve.</p>

<p>Still a smooth learning curve does not mean it is intended for everyone. C is
a rather unforgiving language, you better have to had seen the danger of
premature optimization, spaghetti-logic and lack of planning to know why and
how to avoid them (none of these problems are specific to the C language, but
are usually amplified when using it, because you will be on your own).
Now if you had came past this point and wanted something that does not require
years of painful training, understanding more than weird logic due to legacy
crap that nobody wanted to throw away, you might be interested to read this
documentation a little bit further...</p>


<h2><span class="num">II.</span> History</h2>

<p class="note">This part can be skipped for those who would like to dive
directly in this framework. It will explain how this library came into birth,
and where it got its inspiration from.</p>

<p><span class="lettrine">M</span>y first <acronym title="Graphical User Interface">GUI</acronym>
ever written was on AmigaOS 3.0. This system truly impressed me: it was
basically a Unix micro-kernel, with a very user-friendly graphical interface,
very good integration and extremely low overhead. If it sounds familiar, it is
because nearly 10 years later (we were in 1992), Mac OS X was built on the same
foundation (minus low overhead, but with the computing power available when
this system came out, it wasn't a problem anymore). Still, despite being well
documented, the API was a major PITA: no garbage collection at all (everything
had to be freed manually, otherwise you got a permanent memory-leak), no native
memory segmentation, GUI components lacking in several areas (no multi-line edit
control, limited copy/paste in edits, no multi-column list view, no tabs, no
layout manager, ...), worst, after Commodore bankruptcy, little progress were
expected to happen.</p>

<div class="sep"></div>

<p><span class="lettrine">I</span> then bitterly switched to Linux, with which Amiga shared its roots. After
years of hacking through various framework, it was clear that user-friendliness
and integration weren't the main goal of the various desktop environment.
The root of the problem could easily be traced back to X11 (the part that
manages the display). Despite having decent performances for a full client/server
architecture, its greatest weakness was the poor state of its surrounding
framework (or actually, its lack of framework): basically the only thing you
could do with X11 is drawing line, rectangles, text and bitmap. If you wanted
more, like menus, buttons, list, printing, desktop interaction, ... close to
nothing existed (well, some may dare to mention <em>Athena Widget</em>, known as Xaw,
but the least that can be said about it, is that it completely missed the
"user-friendly" target).</p>

<p>So what shouldn't happen, happened : dozen of framework poped up, using
incompatible APIs, giving a very inconsistent look'n feel to the whole system,
with a more than poor overall integration between applications (even simple
things like cut and paste didn't always work seamlessly, not to mention drag'n
drop). For someone coming from AmigaOS, it could hardly be considered as an
improvement.</p>

<p>Still, among all the framework, there was one which stand up for having a very
simple-to-use API: Motif (known as Xm). Although its license agreement could
hardly be more locked down, and would ultimately be its downfall, there was two
aspects that were amazingly well engineered:</p>
<ol>
  <li>The core framework in which you do most of your application were composed
  of less than 20 functions. No need to remember countless of functions and
  datatypes, including all of their quirks, you truly had the feeling that
  the framework was working for you, and not the opposite.</li>

  <li>Widget Geometry: instead of computing manually positions of all your
  controls (taking into account font size and possibly internationalization),
  you could specify linear constraints between them. I know from this day on,
  that I would never want to use something more simple than that.</li>
</ol>

<p>But the more than closed nature of Motif was its fatal blow. When
<acronym title="GIMP ToolKit">GTK</acronym> was
put into motion to replace Motif with a more liberal license, you know the latter
was living its last days. Way too many years later, the Open Group finally
released Motif under <acronym title="GNU Public License">GPL</acronym> terms, but unsurprisingly, it gained little to no
traction, since its look'n feel were long obsoleted, not to mention a code
base with a very steep learning curve that does not help attracting potential
contributors.</p>

<p>Sadly, GTK was a mess of its own: extremely poor productivity, plain look'n
feel not very eye-appealing (hopefully it could be themed), worst: the first
versions of Gnome desktop environment (which had GTK as its foundation) were
the perfect case study of over-engineering gone mad. In the early 2000, I got
that strange feeling that desktop on Linux was going into a dead end. Designed
by nerds for nerds, who can manage everything through an XTerm console.
Since black and white text interface wasn't my ideal, I decided to move for
greener pasture.</p>

<div class="sep"></div>

<p><span class="lettrine">I</span>t was those ubiquitous green hills that
welcomed me on my brand new laptop, featuring one of my most despised operating
system: Microsoft Windows XP. I hated so much thing, starting with the blue
luna theme, but I had to face the truth: Microsoft succeeded where every others
failed: it gained traction from users and developpers, making any of its
weakness completely irrelevant. I started digging in its API, and as a true
hater, I had to acknowledge that it was based on lots of misconceptions:</p>

<ul>
  <li>The API contains lots of ancient stuff and sometimes weird logic. Not every
  combinations worked as expected, some were even outright rubbish (memory
  management within ComboBox and ListBox), but overall it was pretty stable (though
  a little bit over-documented: it is sometimes hard to know what is cruft, and
  what is really useful, not to mention the somewhat poor quality of examples
  given on MSDN).</li>

  <li>Despite being somewhat outdated, the desktop API was still light-years ahead
  of any operating system made during the nineties. Linux didn't even came
  close until the end of the first decade of 2000. No wonder that at its height,
  Windows accounted for 95% market share and still remain strong.</li>
</ul>

<p>While starting to have the feeling that something more simple was needed, I
watch and embrace the rise of the web. One of the few framework that remember
me the nice engineering of Motif: long but rather flat learning curve, not
just another uninspired and boring API that constantly goes into your way to
build your application. Although browser were incredibly fast and rather
lightweight considering all the benefits for such a high-level API, the overall
architecture requires lots of skill in lots of domain: CSS, Javascript, HTML,
HTTP, and usually a heap of framework on the server side. A rather high
price tag, with which you gain almost universal access to every electronic
device out there. Still, not for everyone (yet).</p>

<div class="sep"></div>

<p><span class="lettrine">S</span>o here I am, feeling there was still lots of room for improvement, especially
after having bitten the dust by using nice but proprietary framework, like Delphi,
C++ Builder and RealBasic (which is far from dead, but I don't have many hopes).
That's why open source is necessary for such kind of framework: there is way too
much to do, in a way too long time frame for a single entity to handle this
correctly. I've done my best to keep the source accessible for everyone
thinking it can do better, because I know for sure that there is little
difference between a poorly engineered open-source framework and a completely
locked-down closed-source binary-only API.</p>

<h2><span class="num">III.</span> Conventions</h2>

<p>Before you read following sections, there is some facts that you must keep in mind,
since they usually won't be stated anywhere else:</p>

<ul>
  <li>The encoding used by this library is <strong>UTF-8</strong>. Every string
  transmitted must be encoded in this charset, and every string you'll get from
  it will be encoded in UTF-8.

  <ul>
    <li><strong>Rationale</strong>: UTF-8 is ASCII compatible, least resistance path
    to unicode compliance, and is not endianess-sensitive.</li>
    <li><strong>Cons</strong>: String modification, especially in C, can be a PITA.
    Sometimes it is easier to temporarily convert the string in UTF-16.</li>
  </ul>
  </li>

  <li>This library makes use of mandatory <strong>namespace</strong>, using traditionnal
  underscore-separated
  prefix common in C. "SIT" is the basic namespace, and to be a little more lexical
  auto-completeness friendly, another letter is used to distinguish different kind of symbols.
  Thus if your IDE is setup to trigger auto-completion after typing 4 letters, it will
  filter unwanted symbols automatically:

  <ul>
    <li><tt>'_'</tt> : Functions and datatypes (i.e: <tt>SIT_CreateWidget()</tt>,
    <tt>SIT_MenuStruct</tt>).</li>
    <li><tt>'_'</tt> : Tag names (i.e: <tt>SIT_Title</tt>, ...)</li>
    <li><tt>'V'</tt> : Tag values (i.e: <tt>SITV_AttachForm</tt>, <tt>SITV_AttachWidget</tt>, ...)</li>
    <li><tt>'E'</tt> : Events (i.e: <tt>SITE_OnClick</tt>, <tt>SITE_OnPaint</tt>, ...)</li>
    <li><tt>'M'</tt> : Menu (<tt>SITM_Toggle</tt>, <tt>SITM_Checked</tt>, ...)</li>
    <li><tt>'K'</tt> : Virtual keys (<tt>SITK_Enter</tt>, <tt>SITK_Space</tt>, ...)</li>
    <li>A few more specialized prefixes exist like <tt>GFX_</tt> for canvas
    related API, <tt>SITTB_</tt> for toolbar, <tt>SITOM_</tt> for OnMouse events...</li>
  </ul>
  </li>

  <li>The following type definitions are used everywhere and thus won't be explained again.
  Keep them in mind, there are not that many:

  <ul>
    <li><tt>STRPTR</tt>: A shortcut for <tt>char *</tt>.</li>
    <li><tt>ULONG</tt>: typedef for <tt>unsigned long</tt>.</li>
    <li><tt>APTR</tt>: alias for <tt>void *</tt>, it means Absolute Pointer.</li>
    <li><tt>Bool</tt>: enumeration that can take the value of <tt>True</tt> (1) or <tt>False</tt> (0).</li>
    <li><tt>SIT_Widget</tt>: opaque type that identify a control within this library.</li>
  </ul>
  </li>

  <li>Minimal version of common control library required is 5.8 (<strong>Windows 2000</strong>
  with Internet Explorer 5 installed), although this library makes use of some extensions from
  v6.0 (<strong>XP</strong>). It has been built using
  MinGW (gcc 3.4) and Code::Blocks IDE, so no heavy-weight tools like Visual Studio
  is required in order to use it. Still, whatever tool you will use, be sure to have
  at least a code-completion feature.</li>
</ul>

<h2 id="chapter4"><span class="num">IV.</span> Getting started</h2>

<p><span class="lettrine">T</span>his section will present a broad overview of
the framework look'n feel and how to setup your tool chain to get the examples
working. No programming guide can pretend to be complete, without showing what
a "Hello world" program looks like:</p>

<pre><span class="d">#include</span> <span class="o">&lt;SIT.h&gt;</span>

<span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])
{
	SIT_Log(SIT_INFO, <span class="o">"hello, world"</span>);
	<span class="k">return</span> <span class="o">0</span>;
}</pre>

<p>It will display a popup, with the message "hello, world" and an Ok button to
dismiss the dialog. Those who knows a little bit of Win32 programming, will
immediately notice that it makes use of the <tt>MessageBox()</tt> function,
which for a hello world, is kind of cheating. So let's put a more complete
example, by creating all ourselve:</p>

<pre><span class="d">#include</span> <span class="o">&lt;SIT.h&gt;</span>

<span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])
{
	SIT_Widget app    = SIT_CreateWidget(<span class="o">"HelloWorld"</span>, SIT_APP, <span class="o">NULL</span>, <span class="o">NULL</span>);
	SIT_Widget dialog = SIT_CreateWidget(<span class="o">"Hello"</span>, SIT_DIALOG, app,
		SIT_Font,    <span class="o">"System/30"</span>,
		SIT_Margins, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>,
		<span class="o">NULL</span>
	);
	SIT_CreateWidget(<span class="o">"hello, world"</span>, SIT_LABEL, dialog, <span class="o">NULL</span>);
	SIT_ManageWidget(dialog);

	<span class="k">return</span> SIT_Main();
}</pre>

<p>Before explaining briefly what each function does, you'll need to compile and
link this program. To get past the compilation phase, you'll need to add the
"<tt>include</tt>" directory from SIT distribution in your compiler search path. This
is usually done through the <tt>-I</tt> flag command line option. Note that the
Microsoft SDK is not required to compile the examples.</p>

<p>Then to get a stand alone executable, you'll need to specify the SIT library
itself (usually through the <tt>-l</tt> command line parameter). It is the file
located in <tt>lib/libSIT.a</tt> in the archive.</p>

<p>So, if the above example was saved in "<tt>hello.c</tt>", and SIT was installed
in "<tt>C:\SIT</tt>", the command line to get a complete program would be (using
gcc):</p>

<pre>C:\&gt; gcc.exe -o hello.exe -IC:\SIT\include -lC:\SIT\lib\libSIT.a -lgdi32 hello.c</pre>

<p>If you are using an <acronym title="Integrated development environment">IDE</acronym>,
remember that order of libraries specified in the link phase is important. Usually linkers
process each library sequentially, trying to resolve as many symbols with it, then
continue with the next one. They are usually not smart enough to remember that new
dependencies introduced by a static library can be resolved by an earlier library
specified with <tt>-l</tt> parameter. In the example above, the <tt>SIT.a</tt> will
add symbols from the <tt>gdi32</tt> library. Therefore <tt>gdi32</tt> must be included
<strong>after</strong> <tt>SIT.a</tt>.</p>

<p>Once linking phase succceeded, you can run the resulting program "<tt>hello.exe</tt>".
You should get something close to:</p>

<img src="images/HelloWorld.png" alt="Hello world on Windows XP" class="figure">

<p>Nothing earth-shattering, but it did the job without too much overhead.
Let's focus briefly on some points:</p>

<h3>Includes</h3>

<p>Include files for SIT are brain-dead simple: there is only 2 include files. One
you will need to include in close to every file that will deal with interface
(<tt>SIT.h</tt>) and another one that provides a canvas-like API (<tt>graphics.h</tt>),
that you usually include for handling <tt>OnPaint</tt> event or loading bitmap.</p>

<p>There is another one that you might be interested in: <tt>UtilityLib.h</tt>. This one
provides basic functions for common datatypes like double-linked hist, hash table, DOS
access (directory scan, delete files/dir, ...) with UTF-8 support, strings,
internationalization... It has a separate documentation in the form of autodocs. This
file is automatically included by <tt>SIT.h</tt>.</p>

<h3>Entry point</h3>

<pre><span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])</pre>

<p>This is the function that is called after SIT has finished initializing its
internal structures. Remember what has been said in the previous section: every string
you will get from SIT will be encoded in UTF-8. This includes the parameters
passed to this function (<tt>argv</tt>). <tt>argv[<span class="o">0</span>]</tt>
will contain the name of the program, therefore program's arguments will start at
index 1.</p>

<p>Some command line arguments will be catched by this library and removed from the
list. Here is the complete list:</p>

<ul>
  <li><tt>-sit:debug</tt>: will display the geometry of all the controls within a
  dialog, just before they are about to be moved. This will be printed on the DOS
  console, therefore it is only useful for debug build. See <a href="#pitfalls">geometry
  pitfalls</a> for more information.</li>

  <li><tt>-sit:font</tt>: allows you to change the system font used when no other
  font is specified (through <a href="#SIT_Font"><tt>SIT_Font</tt></a> property). It must
  be followed by a font specification describing the new font you want to use (as expected
  by the <tt>SIT_Font</tt> property). For example: <tt>-sit:font System/150%</tt> will make
  the application use a system font that is 1.5 times bigger than normal (which can be useful
  for high-DPI screen).</li>
</ul>

<h3>Creating the interface</h3>

<p>The whole interface is created using a single function: <tt>SIT_CreateWidget()</tt>.
Expect to see it a lot in your program. Its name was inspired from
<acronym title="X Toolkit Intrinsics">Xt</acronym>, where you instanciated your
controls using <tt>XtVaCreateWidget()</tt> or <tt>XtVaCreateManagedWidget()</tt>.
Widget is a portmanteau word for "Windows Gadget": small windows with specialized
behavior.</p>

<p>This function uses a <tt>NULL</tt>-terminated list of key/value pairs (keys will
also be referred as "tags"). This has the advantage of being rather fault tolerant
(incorrect tags are simply ignored), and you don't have to remember countless of
datatypes. The drawback is you have to be careful with implicit promotion
(for example: a tag asks for an integer, and if your expression got promoted to
a <tt><span class="t">double</span></tt> datatype, you'll certainly get a stack overflow).</p>

<p>Among all the control types this function can create, there is one that is
not a control per se: <tt><a href="#SIT_APP">SIT_APP</a></tt>. This "widget" usually
sits at the root of your control tree. All its children are usually top-level
dialogs. If all of them get closed in a way or another, it will automatically
exits from the main processing loop.</p>

<p>After creating your controls, you usually register callbacks to respond to
user actions, like keystroke, repainting, mouse click, ... Obviously, in
a small example like that, we didn't have any event to process.</p>

<h3>Let it fly!</h3>

<p>Once your dialog has been setup, <tt>SIT_Main()</tt> will enter the main
processing loop and wait for user actions, which will trigger your callback
or use default actions. For example, when closing the dialog, an OnClose event
is sent to the dialog. If you do not cancel the event, the dialog will be
closed, and every children will be destroyed and the memory freed.</p>

<p>This is actually the way most application got written using this toolkit.
You can check out the example section for more complex applications. You'll
see that at their heart, they are not very different from this simple example.</p>

<h2 id="chapter5"><span class="num">V.</span> Digging further</h2>

<p>Now you got a little overview, let's see how an application it usually built
using this framework. It will show the concepts you will need to know and in which
order:</p>

<ol>
  <li>The first step is obviously to build your interface: know which control to
  use and where they will be placed. Placing is usually done at the same time,
  although it is managed in a completely separate process in this library. You'll
  get a mock-up of your final application, which doesn't do anything for now.</li>

  <li>Once you have your interface setup, it is time to add callbacks that will
  handle user actions. This is where the logic of your application will be. For
  proper reusability, it is advised to separate this logic from the callback itself,
  especially if the code itself is rather long (usually more than 20 lines).
  The rule of the thumb is to avoid spreading your logic all over the place, because
  if something goes wrong or if you want to refactor part of your interface, you'll
  have hard time to check all possible places. If it is your first try in building
  a graphical application, keep in mind that variables tend to pile up quickly.
  Don't hesitate to pack everything up in an opaque structure and use functions
  to access/modify its content. Check the examples section for some not-so-trivial
  programs that do this thing correctly.<br>
  <br>
  This is actually an aspect that is much harder to get right than it seems. Usually,
  whatever language you'll use, don't be discouraged if you didn't get it the first
  try.</li>

  <li>Now your application starts doing some stuff, time to add some polish:
  icons, internationnalization, multi-thread if needed, ressources. You usually
  do this as late as possible, because it is time consuming, time that
  could have been spent on building the actual application. Remember that an
  application that is not very eye-appealing is still better that an application that
  does nothing. It is a mistake that also must not be underestimated.</li>

  <li>Deployment. Usually you package everything into a auto-run installer. This
  part is obviously out of the scope of this documentation, and although its language
  is not that fun, if not outright rubbish, we recommend you to have a look at
  <a href="http://nsis.sourceforge.net/">NSIS</a>.</li>
</ol>

<p>The following sections will explain each of this points more in details. The
complete description of every possible attributes will be described in a separate
guide (the reference chart), because it would be a waste of time digging in this
document each time you wanted to know what range of values an attribute can accept.</p>

<h2><span class="num">VI.</span> Controls and Geometry</h2>

<p><span class="lettrine">I</span>f there is only one chapter to read in this whole
documentation, this is the one, since unless you already know Motif, the approach
taken by this library is not that common. This section will explain you how to create
your controls and how to give some hints to the library in order to place them with
least amount of effort.</p>

<h3>Creating the hierarchy</h3>

<p>Widgets/controls within this library are supposed to be organized in a tree-like
structure: some controls are leaves (push buttons, checkbox, ...), some others are
branches, that will contain one or more children (tabs, dialogs, toolbar, ...). The root
of the tree in a little bit special: it is used to track which dialog remained
opened, and if all of them get closed, it will initiate a graceful exit.</p>

<p>To create this root, and actually all of your controls, you'll use the following
function:</p>

<pre>SIT_Widget SIT_CreateWidget(STRPTR name, int type, SIT_Widget parent, ...);</pre>

<p>Let's emphasized once again the importance of this function, you better have to
memorize its prototype now. Each parameters have the following meaning:</p>
<ul>
  <li><tt>name</tt>: an arbitrary name you want to give to your control. It can
  be whatever you want, don't have to be unique, can contain spaces or unicode
  characters, but cannot be <tt>NULL</tt> or the empty string. For some controls
  this parameter serves also as a shortcut for the <tt>SIT_Title</tt> tag. The
  name can be helpful if you want to find the control by its name using
  <tt>SIT_GetById()</tt>.</li>

  <li><tt>type</tt>: the type of widget you want to create. An enumeration that
  will actually be described a little bit more in detail in the next chapters.</li>

  <li><tt>parent</tt>: where in your hierarchy your control will be inserted. It
  cannot be <tt>NULL</tt> except when the type parameter is <tt>SIT_APP</tt>.</li>

  <li><tt>...</tt>: a <tt>NULL</tt>-terminated list of key (or tag) / value pairs.
  Obviously the list of keys a control accepts depend on its type. Also keep in
  mind that order in which tags are specified does not matter. The complete
  list of tags will be found in the reference chart, this guide will only explain the
  most important ones.</li>
</ul>

<p><tt>SIT_APP</tt> widget currently accepts only one tag: <tt>SIT_UniqueApp</tt>,
which expects a boolean value as argument (which by default is set to <tt>False</tt>).
If overridden to <tt>True</tt>, it will try to find another application with the same
name (first argument to <tt>SIT_CreateWidget()</tt>) and notify the first application
that registered that name, by sending an <tt>OnActivate</tt> event to the
<tt>SIT_APP</tt> widget.</p>

<p>You don't really have to check the return code for every call to
<tt>SIT_CreateWidget()</tt>, since if parent is <tt>NULL</tt>, all subsequent
attempt to create a widget will fail, until you call <tt>SIT_Main()</tt>, which
will notice that no windows are opened and quits immediately.</p>

<p>Also, remember that tag names are prefixed by <tt>SIT_</tt>, and enumeration values
by <tt>SITV_</tt>, so if the first member of the pair does not start with
<tt>SIT_</tt>, it is the sign that something is wrong with the code. To make
this problem more obvious, it is strongly advised to indent your code into
two columns for tag/value list, like this:</p>

<pre>SIT_Widget dialog = SIT_CreateWidget(<span class="o">"Hello"</span>, SIT_DIALOG, app,
	SIT_Font,    <span class="o">"System/30"</span>,
	SIT_Margins, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>,
	<span class="o">NULL</span>
);</pre>

<p>Which is another aspect heavily under-estimated by beginners, which tend to
dismiss long-term maintainability for immediate on-screen results.</p>

<p>If you keep that in mind, you are ready for the next step: creating your
interface, by first creating a top-level dialog, using the same function, but
using <tt>SIT_DIALOG</tt> as for the type parameter. Once you get a reference
on such a widget, you can start adding children controls within the dialog.
The various control types that can be created will be examined more thoroughly
in the next chapter, along with their specific properties they accept. For now,
we will focus on a very critical aspect, that was almost the main reason why
this library was created in the first place: laying your control within the
dialog.</p>

<h3>Placing controls</h3>

<p>Geometry management is a way to specify how to layout your controls on a
dialog, by specifying the least amount of information (the worst case is
having to specify the exact coordinates of all your controls). It was
actually one of the main motivation for creating this library, especially
seeing that so few framework managed this correctly.</p>

<p>The way it works has already been mentionned in the introduction: you specify
linear constraints between controls and/or parent dialog. Instead of giving
specific coordinates and size of each controls, you can say for example that
the right edge of this label has to be put 5 pixels to the left edge of this
edit field, whose right edge will be anchored at 10 pixels from the
right edge of the dialog box.</p>

<p>This way you solve two problems in one shot:</p>
<ol>
  <li>Your application is mostly DPI agnostic: you can change the font size at
  will and your dialog will still be layed out correctly.</li>
  <li>Likewise, this will also allow you to change all the messages of your
  application, while being sure no one will be clipped or leave too much white
  space: internationalization will then mostly consist of marking messages
  to be translated, extract them (a <a href="#msgextract">dedicated tool</a> is available) and then
  provide a translation of the resulting file.</li>
</ol>

<p>You can visualize this as anchors that tied widgets together. As the dialog is
enlarged, it will streches controls that are trapped between two anchors (like the
edit fields in the example below) or move the controls that are attached only on
one side (like the cancel button):</p>

<img id="diagex1" src="images/anchors.png" alt="Geometry management" class="figure">

<p>This toolkit defines 8 types of anchors (will also be referred as
attachments). Here is a broad overview of what each does:</p>

<ol>
  <li><tt>SITV_AttachNone</tt>: This is the default attachment for the position
  and dimension of the control. The default value for the position is the
  point (0, 0), relative to the parent widget. The default value for the
  dimension is the minimal box so that the entire content is visible.</li>
  <li><tt>SITV_AttachForm</tt>: relative to one of the four borders of the
  parent widget.</li>
  <li><tt>SITV_AttachPosition</tt>: relative to a certain percentage of the
  width/height of its parent.</li>
  <li><tt>SITV_AttachWidget</tt>: relative to another widget (has to be in the
  same branch of the control tree).</li>
  <li><tt>SITV_AttachOpposite</tt>: like <tt>SITV_AttachWidget</tt>, but the
  opposite border it usually refers.</li>
  <li><tt>SITV_AttachMiddle</tt>: will align the width/height of the control
  in the middle of width/height of specified widget (usually used by labels,
  like in the example above, where the top position has this kind of
  attachment).</li>
  <li><tt>SITV_AttachNoOverlap</tt>: a mix between <tt>Widget</tt> and
  <tt>None</tt>. This is to help the layout manager to compute the minimal
  dialog size without having widgets overlapping each other. In the example,
  the left side of the cancel button have this kind of attachement, relative
  to the Ok button.</li>
  <li><tt>SIT_MaxWidth</tt>: given a list of widgets, it will set all their
  widths to the widest one. This is usually targetted for labels, or buttons,
  like in the example. As its prefix implies, it is an attribute, not a tag
  value.</li>
</ol>

<p>This seems like a lot, but you will quickly find out that this is just the
bare minimum. The simple example above already uses 6 out of the 8 possible
types of attachment, it is not uncommon to use all the 8 even with a very
simple dialog (actually just adding a button between Ok and Cancel will make
use of all 8 attachments).</p>

<p>Attachments can also be visualize as virtual lines that extend each border of
the controls. Other widgets can then align themselves along those lines. In the
example below, the "Cancel" button has a <tt>Form</tt> attachment on its top
border and a <tt>Widget</tt> type on its left border. Right and bottom are
set to <tt>None</tt>:</p>

<img src="images/attach_form%2Bwidget.png" alt="Example of Form and Widget attachment" class="figure">

<p>One critical point to keep in mind is that <strong>horizontal constraints are
evaluated independently from vertical ones</strong>. This is particularly
critical when trying to avoid circular dependencies (for which the layout
manager will fail harshly). It is usually not that hard to avoid them in one
direction, but with both directions, it happens quite often that two controls
refer to each other (in the first example above, the labels have their vertical
attachment set to the middle of the height of the edit fields, while the left
border of those edits is attached to right side of the labels).</p>

<p>Now you had an overview of how geometry is managed, it is time to know how
to specify them using the correct tag/value pairs.</p>

<h3>Attachment specification</h3>

<p>To completely define the geometry of your widget, you'll have to specify at
most 4 attachments: one for each border. To do this, there is 4 properties that
are inherited by nearly all controls intended to be used within dialogs:</p>

<ol>
  <li><tt>SIT_LeftAttachment</tt></li>
  <li><tt>SIT_TopAttachment</tt></li>
  <li><tt>SIT_RightAttachment</tt></li>
  <li><tt>SIT_BottomAttachment</tt></li>
</ol>

<p>All of them take a single argument: the type of attachment you might want
to apply to the specified border (<tt>SITV_Attach*</tt>). The <tt>Widget</tt>,
<tt>Opposite</tt>, <tt>NoOverlap</tt> and <tt>Middle</tt> types of attachment
require a relative widget to do their job (otherwise you'll get an error,
and your program will exit immediately). This is done using another set of
attributes:</p>

<ol>
  <li><tt>SIT_LeftObject</tt></li>
  <li><tt>SIT_TopObject</tt></li>
  <li><tt>SIT_RightObject</tt></li>
  <li><tt>SIT_BottomObject</tt></li>
</ol>

<p>The expected argument for this kind of attributes is a <tt>SIT_Widget</tt>
object, obtained by a former call to <tt>SIT_CreateWidget()</tt>. Remember that
the order in which tags are given to <tt>SIT_CreateWidget()</tt> <strong>does not
matter</strong>, you can set <tt>SIT_LeftObject</tt> before
<tt>SIT_LeftAttachment</tt> for example. You can even set these properties for
attachment that does not require a relative object (<tt>None</tt>, <tt>Form</tt>,
...), the argument will be simply ignored. Even better: geometry properties don't
have to be set at creation time, this is particularly important when you have
two widgets refering to each other.</p>

<p>There is a third group of properties that you might find interesting:
usually you'll want to specify some space between your control and its
attachment. This is done using this set of properties:</p>

<ol>
  <li><tt>SIT_LeftOffset</tt></li>
  <li><tt>SIT_TopOffset</tt></li>
  <li><tt>SIT_RightOffset</tt></li>
  <li><tt>SIT_BottomOffset</tt></li>
</ol>

<p>With this 3 groups of properties in mind, we can now see more precisely how
they are applied on each attachment type:</p>

<dl id="attachspec">
  <dt>SITV_AttachNone</dt>
  <dd>This is the default attachment for all 4 borders, unless specified otherwise
  (like toolbars for example). Usually this kind of attachment is useful to
  automatically compute the optimal width and height of your controls (like labels,
  buttons, ...). Offsets and Object groups are ignored. If you want to manually
  specify everything, you'll have to use another set of properties (<tt>SIT_X</tt>,
  <tt>SIT_Y</tt>, <tt>SIT_Width</tt> and <tt>SIT_Height</tt>)</dd>

  <dt>SITV_AttachForm</dt>
  <dd>This will attach your control to the same side of the dialog than the side
  where this property has been set (if set to <tt>SIT_LeftAttachment</tt>, it
  will be attach to the left side of the dialog, ...). Object group is ignored,
  but offset will specify the distance between your control and the dialog's
  border.</dd>

  <dt>SITV_AttachPosition</dt>
  <dd>A more generalized version of <tt>SITV_AttachForm</tt>, which allows the
  sides of your control to be relative to a fraction of dialog's width/height.
  Left and Right attachment will always be relative to the width, and Top/Bottom
  will always be relative to the height. To do this, set the corresponding
  Object property using the macro <tt>SITV_AttachPos(percent)</tt>. Offset
  will also be taken into account, can be negative or use the special value
  <tt>SIT_OffsetCenter</tt>. This will set the offset to (-width/2) or
  (-height/2).<br><br>

  Knowing this, setting an <tt>SITV_AttachForm</tt> on the left border, is like
  specifying a <tt>SITV_AttachPosition</tt> with <tt>SIT_AttachPos(0)</tt> as
  argument for the corresponding <tt>Object</tt> group.</dd>

  <dt>SITV_AttachWidget</dt>
  <dd>A very useful attachment, if not the most. It will align the border where
  this attachment is set with the <strong>opposite</strong> border specified
  in the corresponding Object attribute. For example setting a widget attachment
  on the left border, will align this border with the right border of the
  widget specified in the <tt>Object</tt> property. <tt>Offset</tt> will specify
  the distance between the two controls involved.</dd>

  <dt>SITV_AttachOpposite</dt>
  <dd>Similar to <tt>Widget</tt> attachment, it will align the border where it
  is set, to the <strong>same</strong> border specified in <tt>Object</tt>
  property.<br>
  <br>
  Strictly speaking, you might object that semantics between Opposite and
  Widget should be inverted. Just remember that "Opposite" does not refer to
  the border it is attached, but the opposite of what is actually done in
  <tt>Widget</tt> type of attachment. <tt>Widget</tt> attachment is usually
  more common, that's why intuitiveness prevails over semantic.</dd>

  <dt>SITV_AttachMiddle</dt>
  <dd>This kind of attachment is usually only set on top or left border. It
  will center the width/height of your control within the width/height of
  the <tt>Object</tt> control.
  </dd>

  <dt>SITV_AttachNoOverlap</dt>
  <dd>This one is similar to <tt>Widget</tt>, but instead of attaching two
  borders, it will make sure that the border which has this attachment will
  not overlap the opposite border of the control you specify in the
  <tt>Object</tt> property. You can set the corresponding <tt>Offset</tt>
  property to indicate the minimal distance between the two controls.
  </dd>
</dl>

<p>That's for the generic property, there is a few more specialized attributes
that you might find useful.</p>

<h3>Abbreviation</h3>

<p>With all this information, you are now very close to know how to completely
layout the <a href="#diagex1">first example</a> given at the beginning of this
section. The cancel button for example can be specified using the following
statement:</p>

<pre>SIT_Widget cancel = SIT_CreateWidget(<span class="o">"Cancel"</span>, SIT_PUSHBUTTON, dialog,
	SIT_TopAttachment,   SITV_AttachWidget,
	SIT_TopObject,       separator,
	SIT_TopOffset,       <span class="o">5</span>,
	SIT_LeftAttachment,  SITV_AttachNoOverlap,
	SIT_LeftObject,      ok,
	SIT_LeftOffset,      <span class="o">5</span>,
	SIT_RightAttachment, SITV_AttachForm,
	SIT_RightOffset,     <span class="o">10</span>,
	<span class="o">NULL</span>
);</pre>

<p>Which is rather verbose: 20 arguments, 11 lines. There are hopefully shortcut
properties for specifying a whole group (<tt>Attachment</tt>, <tt>Object</tt>
and <tt>Offset</tt>) using a single property:</p>

<ul>
  <li><tt>SIT_Left</tt></li>
  <li><tt>SIT_Top</tt></li>
  <li><tt>SIT_Right</tt></li>
  <li><tt>SIT_Bottom</tt></li>
</ul>

<p>Each of these properties expect exactly 3 arguments: the <strong>attachment</strong>
type, the relative <strong>widget</strong> (you can give NULL if it is not
applicable) and the <strong>offset</strong>. Once again, be very careful to
not forget any arguments, because the library would have no means to recover,
not even to detect it. Using these shortcut properties, the cancel button can also be
instanciated using the following function call:</p>

<pre>SIT_Widget cancel = SIT_CreateWidget(<span class="o">"Cancel"</span>, SIT_PUSHBUTTON, dialog,
	SIT_Top,   SITV_AttachWidget,    separator, <span class="o">5</span>,
	SIT_Left,  SITV_AttachNoOverlap, ok,        <span class="o">5</span>,
	SIT_Right, SITV_AttachForm,      <span class="o">NULL</span>,      <span class="o">10</span>,
	<span class="o">NULL</span>
);</pre>

<p>Which is a little more easier to read. Still, we'll see <a href="#chapter10">another
way</a> to construct your interface, especially when it contains lots of controls,
because it can become tedious to write it that way.</p>

<h3>Other attributes</h3>

<p>Container widgets (dialog, tab, group box, ...) can also specify margins.
This is useful if you want to avoid specifying an offset each time you use a
<tt>Form</tt> attachment. This can be achieved using the following group of
properties:</p>

<ul>
  <li><tt>SIT_MarginLeft</tt></li>
  <li><tt>SIT_MarginTop</tt></li>
  <li><tt>SIT_MarginRight</tt></li>
  <li><tt>SIT_MarginBottom</tt></li>
</ul>

<p>Or you can use the abbreviated property: <tt>SIT_Margins</tt>, which expect
4 integers as arguments (once again, be careful not to miss one!), to set
respectively the top, right, bottom and left margins. Web developpers might
notice that this is the same order than CSS container edge properties
(border, padding, margin). For those who have a Win32 background, those
properties does not alter the non-client area of the window (except for
canvas).</p>

<p>Also margin properties can still be overridden using negative offsets for
<tt>SITV_AttachForm</tt> attachment. This is useful if you want some of your
widgets to extend past margins boundaries, like splitters or separators.
Note however that this library will not allow you to position widgets outside
dialog visible area: if you want to hide a control, you'll have to use
<tt>SIT_Visible</tt> property. This behavior will be explained more in detail
in the next section.</p>

<p id="manualgeom">Still, despite all these properties, you might
still want to manually configure your control, especially the width and/or
height, since for some controls (canvas, listbox, ...) the default dimension
is 10x10px. To do this, there is another set of 4 properties available:</p>

<ul>
  <li><tt>SIT_X</tt></li>
  <li><tt>SIT_Y</tt></li>
  <li><tt>SIT_Width</tt></li>
  <li><tt>SIT_Height</tt></li>
</ul>

<p>You will still be able to specify constraints on left and right border, even
if you have given a value for <tt>SIT_Width</tt>. That way, you'll guarantee
that initial width of your control will be no less than the amount you
specified. There is also a shortcut property for this group: <tt>SIT_Rect</tt>,
which expects 4 integers as arguments, in the order listed above.</p>

<p>If you made your dialog resizable, the minimal width and/or height you set
explicitely might be a little bit too big, and would like to allow your controls
to be resized smaller than the initial dimension. This is done through the
properties <tt>SIT_MinWidth</tt> and <tt>SIT_MinHeight</tt>. It is especially
useful for canvas or listbox, where you want to give them a reasonable
width/height initially, but allow them to be resized much smaller than
that later on.</p>

<p>The last remaining property you might be interested in is <tt>SIT_MaxWidth</tt>,
mentionned at the beginning as the 8th attachment kind. The expected argument is a
<tt>SIT_Widget</tt>. You have to create a linked list between controls that will
shared the maximal width. For example:</p>

<pre><span class="c">/* Create some widgets */</span>
SIT_Widget label1 = SIT_CreateWidget(<span class="o">"Label1:"</span>, SIT_LABEL, dialog, <span class="o">NULL</span>);
SIT_Widget label2 = SIT_CreateWidget(<span class="o">"Another label:"</span>, SIT_LABEL, dialog,
                        SIT_MaxWidth, label1, <span class="o">NULL</span>);
SIT_Widget label3 = SIT_CreateWidget(<span class="o">"Last:"</span>, SIT_LABEL, dialog, <span class="o">NULL</span>,
                        SIT_MaxWidth, label2, <span class="o">NULL</span>);
</pre>

<p>Once again, avoid circular dependencies.</p>

<h3>Summary</h3>

<p>Just to sum up what we've seen so far, here is the table of the 29 properties
related to geometry management:</p>

<div class="table">
<table>
<thead>
  <tr><td>Name</td><td>Type</td><td>Description</td>
</thead>
<tbody>
<tr>
  <td><tt>SIT_LeftAttachment</tt></td>
  <td rowspan="4"><span class="t">enum</span></td>
  <td rowspan="4">Border attachment type. See <a href="#attachspec">attachment
  specification</a> for possible values.</td>
</tr><tr>
  <td><tt>SIT_TopAttachment</tt></td>
</tr><tr>
  <td><tt>SIT_RightAttachment</tt></td>
</tr><tr>
  <td><tt>SIT_BottomAttachment</tt></td>
</tr><tr>
  <td><tt>SIT_LeftObject</tt></td>
  <td rowspan="4">SIT_Widget</td>
  <td rowspan="4">Another control relative to the attachment specified (if applicable)
  or percentage in case of a <tt>SITV_AttachPosition</tt>.</td>
</tr><tr>
  <td><tt>SIT_TopObject</tt></td>
</tr><tr>
  <td><tt>SIT_RightObject</tt></td>
</tr><tr>
  <td><tt>SIT_BottomObject</tt></td>
</tr><tr>
  <td><tt>SIT_LeftOffset</tt></td>
  <td rowspan="4"><span class="t">int</span></td>
  <td rowspan="4">Distance in pixel between control and attachment.</td>
</tr><tr>
  <td><tt>SIT_TopOffset</tt></td>
</tr><tr>
  <td><tt>SIT_RightOffset</tt></td>
</tr><tr>
  <td><tt>SIT_BottomOffset</tt></td>
</tr><tr>
  <td><tt>SIT_Left</tt></td>
  <td rowspan="4"><span class="t">enum</span>,&nbsp;SIT_Widget,&nbsp;<span class="t">int</span></td>
  <td rowspan="4">Shortcut for a group of attachment, object and offset properties. Has to
  be specified in this order.</td>
</tr><tr>
  <td><tt>SIT_Top</tt></td>
</tr><tr>
  <td><tt>SIT_Right</tt></td>
</tr><tr>
  <td><tt>SIT_Bottom</tt></td>
</tr><tr>
  <td><tt>SIT_MarginTop</tt></td>
  <td rowspan="4"><span class="t">int</span></td>
  <td rowspan="4">Specify a distance between container's edges and content. Works for: SIT_PUSHBUTTON, SIT_CANVAS, SIT_DIALOG, SIT_FRAME and SIT_TAB.</td>
</tr><tr>
  <td><tt>SIT_MarginRight</tt></td>
</tr><tr>
  <td><tt>SIT_MarginBottom</tt></td>
</tr><tr>
  <td><tt>SIT_MarginLeft</tt></td>
</tr><tr>
  <td><tt>SIT_Margins</tt></td>
  <td><span class="t">int</span>, <span class="t">int</span>, <span class="t">int</span>, <span class="t">int</span></td>
  <td>Shortcut for specifying top, right, bottom and left margin.</td>
</tr><tr>
  <td><tt>SIT_X</tt></td>
  <td rowspan="4"><span class="t">int</span></td>
  <td rowspan="4">Manual positionning of control. Strongly advised to avoid setting
  explicitely X and Y. Width and Height can be useful to override default
  heuristic.</td>
</tr><tr>
  <td><tt>SIT_Y</tt></td>
</tr><tr>
  <td><tt>SIT_Width</tt></td>
</tr><tr>
  <td><tt>SIT_Height</tt></td>
</tr><tr>
  <td><tt>SIT_Rect</tt></td>
  <td><span class="t">int</span>, <span class="t">int</span>, <span class="t">int</span>, <span class="t">int</span></td>
  <td>Shortcut for specifying X, Y, Width and Height of control.</td>
</tr><tr>
  <td><tt>SIT_MinWidth</tt></td>
  <td rowspan="2"><span class="t">int</span></td>
  <td rowspan="2">Minimal size the control is allowed to be resized. Used by:
  canvas and listbox. Editbox, slider, progress, combobox and datetime will
  only honor MinWidth. The toolbar control will honor MinWidth or MinHeight
  depending if it is a vertical or horizontal toolbar.</td>
</tr><tr>
  <td><tt>SIT_MinHeight</tt></td>
</tr><tr>
  <td><tt>SIT_MaxWidth</tt></td>
  <td>SIT_Widget</td>
  <td>Linked list of control that will shared the same width.</td>
</tr>
</tbody>
</table>
</div>

<h3>Relation with dialog size</h3>

<p>Now that you know how to specify constraints between your controls,
you need to know how the layout manager will be able to deduce the optimal
dimension of the top level window. This process is done in two passes:</p>

<ol>
  <li>The layout manager will compute the minimal width of your dialog, so
  that no controls overlap each other, according to the constraints you've
  specified. It will use this information to constraint the resize
  handle.</li>
  <li>Then, if the width or height you specify manually for the dialog is
  greater than the minimal dimension, another pass will be done to
  take into account the size you've given. User will still be able to
  reduce that size down to the optimal minimum.</li>
</ol>

<p>Keep in mind that, with this behavior you cannot place control outside
visible view, because dialog will be automatically enlarged. If you want
to completely hide a control, use the <tt>SIT_Visible</tt> property. A hidden
control will be skipped by the layout manager.</p>

<p>Also, if there is no controls that have a <tt>Form</tt> attachment on the
right (respectively bottom) side, the layout manager will block resizing
operation on the width (respectively height). If both sides are blocked,
you are advised to give the <tt>SITV_NoResize</tt> flag to the
<tt>SIT_Styles</tt> tag for your dialog. That way resizing cursors won't
appear when the mouse is over the edges of the dialog.</p>

<h3>Dynamic behavior</h3>

<p>So far we have seen how to setup constraints before anything is visible on
the screen. There is some caveats to be aware when modifying contraints on the
fly.</p>

<p>One critical point to keep in mind, is that any modifications done within a
callback will only be taken into account after returning to the main event loop
(ie: exiting from your function, usually a callback). In the meantime, you can
do whatever you want, including adding, removing (<tt>SIT_RemoveWidget()</tt>)
or hidding controls (through the property <tt>SIT_Visible</tt>), changing
constraints, all those modifications will be analyzed after you give the
execution back to this library.</p>

<p>Some properties other than the geometry-related group might alter the size
of some controls. For example, when changing the text of a label or a push
button, one might expect that control's size is adjusted accordingly. By default
they will, although this behavior can be controlled through the <tt>SIT_ResizePolicy</tt>
property, which can be assigned to one of the following values:</p>

<ul>
  <li><tt>SITV_Auto</tt>: control size will be adjusted so that optimal
  size will always reflect widget content (this is the default for all
  controls, including dialogs).</li>

  <li><tt>SITV_Fixed</tt>: this one means that control's optimal size is
  computed only once. After that, only geometric constraints can alter
  its size.</li>
</ul>

<p>Another point to keep in mind is to know what happen to geometry constraints
when you hide or remove a control, while other widgets use it as a relative
anchor. The way the library handle this case is to assign the contraint of each
side of the widget being removed/hidden to the same side of any other widget
that has a reference to the former. Consider this example:</p>

<img src="images/constraint_sample.png" alt="Constraint sample">

<p>The progress bar has its left edge attached to the right edge of the "Close"
button, and the left edge of the "Close" button is attached to the right edge
of the "Change" button. What happens if you remove/hide the "Close" button?
Since the left attachment of the progress bar is no more valid, the left
attachment of the "Close" button will then be assigned to the left attachment
of the progress bar, which gives the following result:</p>

<img src="images/widget_removed.png" alt="After removal of Close button">

<p>In case the button is only hidden instead of removed, this behavior is
temporary. If you didn't change the constraints in the meantime, next time you'll
unhide the "Close" button, the left attachment of the progress will be restored,
ie: you'll get again what you have in the first example.</p>

<p>You still have to be careful with controls you hide. In the example above,
the list box has its bottom attachment set relative to the "Change" button. If
you ever hide that button, the listbox will inherit its bottom attachment, that
is the bottom of the form, overlapping the "Close" button and the progress bar.
To avoid this, you'll have to also modify bottom attachment of listbox to point
to another control. Remember, attachments will be analyzed only when you
return from your function, so you don't have to worry about chaotic movement
of controls whenever you modify one of its property.</p>

<p>This technique can also be used to alter dialog size after it has been
displayed. Consider the following example, which is a classical login/password/server
authentication dialog:</p>

<img id="diagex2" src="images/LoginScreenExample.png" alt="Sample dynamic behavior">

<p>If done in an user-friendly way, the server should respond to UDP broadcast
datagram to notify its presence to potential clients. By default, you don't
want that list of servers to be displayed, only when clicking on the arrow.</p>

<p>To do this you can create a hidden listbox, whose top attachment is set
relative to server's editbox. When making the list visible, also change the
separator top attachment to make it relative to the list. The list will then
appear correctly, enlarging dialog's height, but if you ever try to resize
the dialog vertically, you would notice that it doesn't work. This is
because there is no widgets that have a <tt>Form</tt> attachment on its
bottom side, so a little more work is needed.</p>

<p>First, we create the listbox with its bottom attachment relative to the
separator, then when it is time to display the list, we change the top
attachment of the separator to <tt>None</tt> and the bottom one relative to
the "Login" button. At last the "Login" button is set relative to the bottom
of the form. That way the dialog become also resizable along its height.</p>

<h3 id="pitfalls">Pitfalls</h3>

<p>Setting up constraints is usually not that hard, but can still lead to
some hard-to-diagnose problems.</p>

<p>The most classical pitfall is having circular dependency between your
constraints. This library has a crude but small algorithm to detect those,
which will be reported through a fatal error (which seems harsh, but better
fix your mistake sooner than later).</p>

<p>Another very common mistake is to forget an argument for a property that
expect multiple values. Since this library has no means of detecting such
problems, it can be rather tedious to diagnose, especially when doing
some heavy refactoring. Remember what has been said in
<a href="#chapter5">chapter V</a>: first build your interface, without
worrying too much about your business logic or cosmetical details. That way you
can concentrate on one thing at a time, instead of having to search for
something wrong all over the place.</p>

<p>It you still didn't get what you expected, you can provide the
<tt>-sit:debug</tt> parameter on the command line. It will print some
information on the command line (which has to be activated, otherwise
you will see nothing. The way to activate this depends on your development
environment). This parameter will display various information about
control positioning every time the layout manager is invoked (which means
quite a lot when resizing the window). It will output something like
this:</p>

<pre>DIALOG: SIT-Test 400x300
- toolbar = 0x0 - 400x24 [1-1], tab:5
  - combo = 1x0 - 88x19 [1-1], tab:10
- addr = 0x24 - 52x276 [1-1], tab:15
- scroll = 383x24 - 17x276 [1-1], tab:20
- hex = 55x24 - 326x276 [1-1], tab:25</pre>

<p>Widgets will be displayed hierarchically, and will include from left to right:
name, position, dimension, whether the control has room (1) or not (0)
to be resized horizontally, then vertically and finally the tab index of the
controls (0 indicating that the control is not part of the focus ring).</p>

<h2 id="chapter7"><span class="num">VII.</span> Events/callbacks</h2>

<p><span class="lettrine">B</span>efore we see the different kind of controls
more in detail, you'll need to have an overview on how events are processed
in this framework. Just like widget creation, event interface uses a
generic approach: you typically register a callback that will be triggered
whenever the action you register it for is notified by the system. You
do this by using the following function:</p>

<pre><span class="t">void</span> SIT_AddCallback(SIT_Widget widget, <span class="t">int</span> type, SIT_CallProc proc, APTR data);</pre>

<p>Each arguments of this function are pretty straightforward, for the sake of
completeness, here are the detailed meaning of each of them:</p>
<ul>
  <li><tt>widget</tt>: The target control that will report the event you want.</li>
  <li><tt>type</tt>: The type of event you want to be notified. Remember that
  event type are prefixed by <tt>SITE_</tt>.</li>
  <li><tt>proc</tt>: Your callback, its prototype will be emphasized below.</li>
  <li><tt>data</tt>: A userdata you can register along with the callback that
  will be given again whenever your callback is invoked.</li>
</ul>

<p>Every callback you'll register for every kind of event, will always use the
same prototype. Remember it well, because you'll use it a lot in every program.
For those who might wonder, yes, this prototype comes straight from <tt>Xt</tt>,
almost unmodified:</p>

<pre><span class="t">int</span> callback(SIT_Widget widget, APTR call_data, APTR user_data);</pre>

<div class="bgtip"><p class="tip">IDE, like Code::Blocks can define abbreviations that can be
expanded to a full declaration. In C::B, go in the menu Settings &#9658; Editor,
then select "Abbreviations". Create an abbreviation named "callback" with the
following text in the body:
<span class="preformat"><span class="t">int</span> |(SIT_Widget widget, APTR call_data, APTR user_data)
{
}</span>
Then whenever you type "<tt>callback</tt>" in the editor, push
<span class="shortcut">Ctrl+J</span> to expand the macro and place the
caret in place of the | character.</p></div>

<p>Once again arguments are pretty straightforward:</p>
<ul>
  <li><tt>widget</tt>: the first argument you gave to <tt>SIT_AddCallback()</tt>, when
  you registered your callback.</li>
  <li><tt>call_data</tt>: this is a data structure that depends on the type
  of callback you register. For example, if you register your callback for an
  <tt>OnPaint</tt> event, <tt>call_data</tt> will point to a graphical context,
  with which you can draw stuff on. A more detailed description will be given below.
  Whatever object is passed to your callback, it remains the property of this
  library. You are usually allowed to modify them (including strings or array), but
  <strong>never attempt to free any of them yourself, nor keep a reference past the
  end of your callback</strong> (unless it is an atomic type), the only thing you
  will get is ludicrously hard-to-diagnose errors.</li>
  <li><tt>user_data</tt>: the fourth argument you gave to <tt>SIT_AddCallback()</tt>.</li>
</ul>

<p>Unless otherwise stated, the <strong>return value</strong> is used to
indicate whether (1) or not (0) you processed the event. If you did not process
the event, some default action might take place, like for example keyboard
event: if you do not process the Tab key, it will be used to navigate between
controls.</p>

<p>Also, another point to keep in mind is that callback will only be triggered
by user actions, not by programatically setting properties. For example, if
you have an <tt>OnChanged</tt> callback registered on an <tt>EditBox</tt>, it
won't be triggered if you programmatically set the <tt>SIT_Title</tt> property.
If you want to trigger the callback chain, you can use the <tt>SIT_ApplyCallback()</tt>
function.</p>

<p>Here is a brief explanation of what to expect for each different kind of
event:</p>

<dl>
  <dt id="SITE_OnClose"><tt>SITE_OnClose</tt></dt>
  <dd>This event is only meaningful for top level dialog. It will give the
  user a chance to be notified from unsaved data that might be loss if the action
  is carried on. The <tt>call_data</tt> parameter passed to the callback is
  a pointer to a <tt class="t">Bool</tt>. Set it to False to cancel the action,
  or leave it as is to close the dialog. Whatever the return code, the value
  of this boolean will decide whether or not the dialog will remain open.</dd>

  <dt><tt>SITE_OnActivate</tt></dt>
  <dd>Triggered when the user wants to perform an action with the control.
  Typicaly, it is used with buttons (push, radio or checkbox), HTML link,
  list box, etc ... <tt>call_data</tt> will usually contain the item id.
  </dd>

  <dt><tt>SITE_OnChange</tt>, <tt>SITE_OnChanged</tt></dt>
  <dd>Two similar events that are intended for edit box. They enable you to
  filter what is being typed within an edit field. <tt>OnChange</tt> is sent
  before anything on screen has been updated, while for <tt>OnChanged</tt>,
  the changes are already visible. The <tt>call_data</tt> is actually a
  pointer to a UTF-8 string (STRPTR). As a permitted hack, it is allowed to modify the
  string (do not write characters beyond <tt>strlen(call_data)</tt>) and
  return 1 in the callback to nofity the changes to the underlying control.</dd>

  <dt id="SITE_OnFocus"><tt>SITE_OnFocus</tt>, <tt>SITE_OnBlur</tt></dt>
  <dd>Another pair of similar events. Used to notify keyboard focus change
  between controls. This is especially useful for Canvas, if you ever want to
  handle the drawing of the focus indicator. <tt>call_data</tt> will be
  <tt class="o">1</tt> for <tt>OnFocus</tt> event, and <tt class="o">0</tt>
  for <tt>OnBlur</tt>. Avoid cancelling those event. If you want your
  focus to remain on a particular control, block focus on the other controls.
  instead.</dd>

  <dt id="SITE_OnFinalize"><tt>SITE_OnFinalize</tt></dt>
  <dd>Will be triggered when the control is about to be destroyed. It will give
  you a chance to free any resources you might have allocated. It is not safe to
  access to the control hierarchy at this point, as other controls might have
  already been deleted. <tt>call_data</tt> will always be
  <tt class="o">NULL</tt>.</dd>

  <dt><tt>SITE_OnClick</tt></dt>
  <dd>This event is used to report mouse actions (left click, right click,
  mouse wheel, ...). Mouse events will be described more in details in the
  next chapter, when talking about canvas. The <tt>call_data</tt> will be a
  pointer to a <tt>SIT_OnMouse</tt> structure (this datatype is not a pointer,
  so don't forget the star when casting the <tt>call_data</tt>).</dd>

  <dt><tt>SITE_OnMouseMove</tt></dt>
  <dd>Will report mouse movement within control. <tt>call_data</tt> will be a
  pointer to a <tt>SIT_OnMouse</tt> structure. It is actually quite common
  to use the same callback for <tt>OnClick</tt> and <tt>OnMouseMove</tt>, so
  much that a shortcut name exists: <tt>SITE_OnClickMove</tt>. It will register
  your callback and associated data for both <tt>SITE_OnClick</tt> and <tt>SITE_OnMouseMove</tt>.
  The <tt>x</tt> and <tt>y</tt> member of the <tt>SIT_OnMouse</tt>
  structure will be relative to top left corner of the control. This event
  and the previous will be described more thoroughly in the next chapter.</dd>

  <dt><tt>SITE_OnClickMove</tt></dt>
  <dd>This is not a real event type, but just a shortcut for registering the
  same callback for both <tt>SITE_OnClick</tt> and <tt>SITE_OnMouseMove</tt>.
  Indeed, it happens quite often to handle (especially mouse movement usually
  only matters after some mouse buttons have been pressed). Note that if you
  want to remove the callback, you will have to do this using the cannonical
  names.</dd>

  <dt id="SITE_OnResize"><tt>SITE_OnResize</tt></dt>
  <dd>Whenever any of your control (including dialog box) is about to be
  resized, this event will be triggered. The <tt>call_data</tt> parameter
  will contain a table of 2 ULONGs, specifying the new width and height in
  pixels of the control.</dd>

  <dt><tt>SITE_OnPaint</tt></dt>
  <dd>Used to redraw part of a control and/or dialog. <tt>call_data</tt> is a
  pointer to a graphic context (<tt>GC</tt>) where you can draw whatever you
  want. This event is only meaningful on a small subset of controls: Dialog,
  Canvas, ComboBox, ListBox, Slider and StatusBar. The default handler for
  Dialog and Canvas does not do very much: it simply erases the area with the
  default background color. For the other control, you'll have access to the
  low-level rendering procedure, that will enable you to customize the
  appearance of the control. This event will be explained more in detail in the
  Canvas section of the next chapter.</dd>

  <dt><tt>SITE_OnRawKey</tt>, <tt>SITE_OnVanillaKey</tt></dt>
  <dd>Allow you to get notified by key pressed. <tt>RawKey</tt>
  is for keys that does not have a dedicated unicode character (like cursor
  keys, Shift, Control, Alt, Page Up, ...), while <tt>OnVanillaKey</tt>
  will report the actual character (in unicode code point and UTF-8). Both
  events will pass a pointer to a <tt>SIT_OnKey</tt> structure for the
  <tt>call_data</tt> argument. Returning <tt class="o">1</tt> for this
  event will prevent some default action to take place (some others, like
  menu accelerators, will be processed long before you get a chance to
  cancel them).</dd>

  <dt><tt>SITE_OnScroll</tt></dt>
  <dd>Sent by Slider and ScrollBar to report the new position the user
  set the thumb. The <tt>call_data</tt> can actually be cast to a ULONG
  to get that position.</dd>

  <dt><tt>SITE_OnMenu</tt></dt>
  <dd>Called when user selects a menu entry. <tt>call_data</tt> is an
  integer that specify the ID of the menu entry.</dd>

  <dt><tt>SITE_OnCtxMenu</tt></dt>
  <dd>Will be triggered when it is time to display a context menu. This
  usually happens when the user right clicks over the control or hit the
  dedicated key on the keyboard.
  </dd>

  <dt><tt>SITE_OnSortItem</tt></dt>
  <dd>Only fired by Listbox controls whenever the order of two items must
  be determined. <tt>call_data</tt> will be a pointer to a structure
  <tt>SIT_OnSort</tt>. Will be described more in detail when talking about
  listbox in the next chapter.</dd>

  <dt><tt>SITE_OnTimer</tt></dt>
  <dd>These events are triggered periodically, although you cannot register
  them using the function <tt>SIT_AddCallback()</tt>, because you need a
  timeout parameter for this event to work. To do this, you'll have to use
  this specialized function:

  <pre><span class="t">int</span> SIT_SetTimer(SIT_Widget w, SIT_CallProc, <span class="t">APTR</span> data, <span class="t">int</span> msec);</pre>

  <p><tt>data</tt> is an arbitrary pointer that will be given back through
  the <tt>user_data</tt> parameter of the callback. <tt>msec</tt> is the
  delay in millisecond betweeen each function call (that will be given back
  through the <tt>call_data</tt> parameter of your callback). Note however that this
  is a low precision timer. Do not expect period lower than 10ms, since this
  is the usual time slice attributed per context switch on Windows operating
  system. Moreover, timer events never accumulate: if you are still processing
  something in your callback, while it is time to trigger the next timer event,
  the event will simply be discarded until your callback has finished.</p>

  <p>Having that in mind, timer can be used as idle procedure, simply use <tt class="o">1</tt>
  as for the msec parameter: your procedure will be called whenever the
  event loop is idle.</p>
  
  <p>If you want to reduce the period, or have a more precise/regular timer,
  you will have to start a thread and do an active loop, querying the performance
  counter instead.</p>

  <p>The callback is expected to return <tt class="o">1</tt> if the function
  wants to be called again, or <tt class="o">0</tt> if the timer has to be
  stopped right after.</p>

  <p>The return value from <tt>SIT_SetTimer()</tt> is an integer that you can
  give to the function <tt><span class="t">void</span> SIT_StopTimer(<span class="t">int</span>
  timerid);</tt>. Stopping a timer that does not exist or that is already
  expired will be safely ignored. Also timerid are guaranteed to be unique
  within the lifetime of your program.</p>
  </dd>

  <dt id="SITE_OnDropFiles"><tt>SITE_OnDropFiles</tt></dt>
  <dd>Triggered when files/folders are dropped over the widget where this event
  is registered (usually dialog). The <tt>call_data</tt> parameter will be a
  <tt class="o">NULL</tt>-terminated table of <tt class="t">STRPTR</tt> containing
  the fully qualified path of each dropped objects (UTF8 encoded).
  And as usual, do not keep a reference on those strings past the end of
  your callback.</dd>

  <dt id="SITE_OnUser"><tt>SITE_OnUser</tt></dt>
  <dd>This is special event that can only be sent programmatically, using
  the function <tt>SIT_Notify()</tt>. No direct user action can trigger it.
  It can be useful if another thread wants to notify the main interface about
  some event (like completetion of a lengthy computation). <tt>call_data</tt>
  will be the pointer given as second argument to <tt>SIT_Notify()</tt>.</dd>

  <dt><tt>SITE_OnClipChanged</tt>, <tt>SITE_OnClipRender</tt></dt>
  <dd>Will be described int the chapter dedicated to <a href="#clipboard">clipboard</a>
  management.</dd>

  <dt><tt>SITE_OnSetOrGet</tt></dt>
  <dd>Will be described in the <a href="#chapter9">extra widgets</a> chapter.</dd>
</dl>

<p>Remember that this was just a brief overview. The next section will describe
them more in detail.</p>

<h2><span class="num">VIII.</span> Widgets/Controls</h2>

<p><span class="lettrine">T</span>his chapter will present what controls are
supported by this library, and their expected behavior/quirks. The reference
chart will contain an exhaustive list of all attributes you can set. This is
a long chapter, which basically describes what parameters the <tt>SIT_CreateWidget()</tt>
function can take. You can safely skip to the next chapter, if you do not
want to deal with that load of details now.</p>

<h3>SIT_WIDGET</h3>

<p>This is not a real widget per se (it cannot be directly instanciated), but
it contains a few common properties that are shared with almost all other
controls. You have already seen a bunch of them, when talking about geometry
management. There are a few more:</p>

<dl>
  <dt><tt>SIT_Title</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>This property enables you to change the title of dialog, label, buttons,
  edit box and progress bar. All but progress bar and edit box allow you to use
  widget name as a shortcut for this property. If you want to modify it later,
  you'll have to use this property though.</dd>

  <dt><tt>SIT_UserData</tt> (<tt class="t">APTR</tt>)</dt>
  <dd>An arbitrary pointer you want to associate with your widget.</dd>

  <dt><tt>SIT_Enabled</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Enable or disable the control. If it is disabled, all children will also
  be disabled. When re-enabled, the children will get the state they had before.</dd>

  <dt><tt>SIT_Visible</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Show or hide a given control and/or dialog. By default dialogs are created
  hidden, to give you room to populate them with controls, while controls are
  created visible. This can be overridden at creation time or afterward.</dd>

  <dt><tt>SIT_TabOrder</tt> (<tt class="t">int</tt>)</dt>
  <dd>This property specifies in which order, controls will be scanned using
  the tab key. Unless you specify otherwise, this property will already be
  filled for you. If you want to exclude a control from the focus ring, specify
  0 for this property.</dd>

  <dt><tt>SIT_Cursor</tt> (<tt class="t">int</tt>)</dt>
  <dd>Allows you to change the shape of the cursor when the mouse is over the
  control (or dialog). Possible values begin with <tt>SITV_Cursor*</tt>.</dd>

  <dt><tt>SIT_Parent</tt> (<tt>SIT_Widget</tt>)</dt>
  <dd>The parent of the widget. Will be NULL for a <tt>SIT_APP</tt> widget.</dd>

  <dt><tt>SIT_CtrlType</tt> (<tt class="t">int</tt>)</dt>
  <dd>Get the type of the control (second parameter of <tt>SIT_CreateWidget()</tt>).
  This property is read-only.</dd>

  <dt id="SIT_Font"><tt>SIT_Font</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd><p style="margin-top: 0">Allows you to change the font the control is using. Unless explicitely
  set, child controls inherit the font that has been set on the top-level
  dialog, which by default equals <tt class="o">"System"</tt> (can be
  overridden using the <tt>-sit:font</tt> command-line parameter). A font
  specification is a string that is composed of a font name followed by
  a slash-separated list of optional attributes, among:</p>

  <ul>
    <li><tt>underline</tt></li>
    <li><tt>bold</tt></li>
    <li><tt>italic</tt></li>
    <li><tt>strike</tt></li>
    <li><tt>noaa</tt> (disable cleartype even if it is activated).</li>
    <li><em>number</em>: it specifies the font size in pixels. A percent sign can
    follow the number to indicate that the size is relative to system font height. It
    is strongly encouraged to always specify a relative size, so that your control
    will adjust properly on any DPI setting.</li>
  </ul>

  <p>Moreover, there are 2 predefined font names (note that font names are not case
  sensitive):</p>

  <ul>
    <li><tt>system</tt>: default variable-pitch font (as set in the control panel).</li>
    <li><tt>fixed</tt>: default fixed-pitch font (as of now: <tt>Courier New</tt>).</li>
  </ul>

  <p>A few examples:</p>
  <ul>
    <li><tt class="o">"System/110%"</tt>: default variable-pitch font, 1.1 times bigger.</li>
    <li><tt class="o">"System/bold/90%"</tt>: System font, bold and 1.1 times smaller.</li>
    <li><tt class="o">"Consolas"</tt>: <tt>Consolas</tt> font using the same size than
    system font.</li>
    <li><tt class="o">"System/30"</tt>: sytem font, 30 pixels tall.</li>
  </ul>
  </dd>

  <dt><tt>SIT_BuddyLabel</tt> (<tt class="t">STRPTR</tt>, <tt class="t">SIT_Widget *</tt>)</dt>
  <dd>This property can only be set at creation time. It will allow you to
  create a label to the left of a given control (using half the font height as
  offset), with the text right-aligned. It is extremely comon to have a label
  next to editbox or combobox, although this property can be applied to any
  control.

  <p>This property expect exactly two arguments: the first is the text of the
  label, the second is a pointer to a <tt>SIT_Widget</tt>, that will receive
  the label. If the value pointed is not NULL, this value will be linked with
  the newly created label through a <tt>SIT_MaxWidth</tt> chain (so don't
  forget to NULLify your pointer before giving it as argument). You can also
  retrieve this widget using <tt>SIT_GetById()</tt>, the name will the same as
  the control for which this property has been set, but prefixed with a <tt>b</tt>
  (for buddy).</p></dd>

  <dt><tt>SIT_TagList</tt> (<tt class="t">KeyVal</tt>)</dt>
  <dd>This tag can be useful if you want to use an array instead of a vararg to
  pass arguments to <tt>SIT_CreateWidget()</tt> or <tt>SIT_SetValues()</tt>.
  The expected argument is an array of <tt>KeyVal_t</tt> structure. It is
  declared like this:
  <pre><span class="t">typedef struct</span>
{
	<span class="t">int</span> tag;
	<span class="t">union</span> {
		<span class="t">ULONG</span> val;
		<span class="t">APTR</span>  ptr;
	} key;
} KeyVal_t;</pre>

  <p>Depending on the type of the property, you either have to initialize
  the <tt>val</tt> or <tt>ptr</tt> field of the union. The table has to be
  ended by a <tt>SIT_TagEnd</tt> (<tt class="o">0</tt>) as value for the
  <tt>tag</tt> member. To initialize such a table, you can use the C99
  notation:</p>
  <pre>KeyVal_t my_args[] = {
    {SIT_Font,    {.ptr = <span class="o">"System/30"</span>}},
    {SIT_Margins, {.val = <span class="o">10</span>}},
    {<span class="o">0</span>,           {.val = <span class="o">10</span>}},
    {<span class="o">0</span>,           {.val = <span class="o">10</span>}},
    {<span class="o">0</span>,           {.val = <span class="o">10</span>}},
    {SIT_TagEnd}
};</pre>
  <p>Take note that any arguments after a <tt>SIT_TagList</tt> will be ignored.</p>
  </dd>
</dl>

<p>Also, for property that expect a String value, you can combine the property
name with the <tt>XfMt</tt> flag. You can then specify a <tt>printf</tt>-like
format string as argument to this property, followed by any argument needed by
the format string itself. Like for example:</p>

<pre>SIT_Widget w = SIT_CreateWidget(<span class="o">"main"</span>, SIT_DIALOG, app,
	SIT_Title | XfMt, <span class="o">"XMines <span class="s">%s</span>"</span>, levels[game-&gt;level].name,
	<span class="o">NULL</span>
);</pre>

<p>A few more specialized attributes exist, check out the reference chart for
the complete list.</p>

<h3 id="SIT_APP">SIT_APP</h3>

<p>Also not a control per se, but it is usually the first widget you have to
create. It only has one property (<tt>SIT_UniqueApp</tt>) and report to
only one event (<tt>SITE_OnActivate</tt>). This event is triggered only
when the <tt>SIT_UniqueApp</tt> has been set to True. It is used to indicate
that another application provided the same name and also requested an
unique instance (which means in 99% of cases that the same
application has been started twice). In that case, the <tt>SIT_APP</tt>
widget will fire a <tt>OnActivate</tt> event, that you can catch.</p>

<p>The <tt>call_data</tt> for this event will actually be a NULL-terminated
string table (<tt class="t">STRPTR *</tt>) that will contain the same arguments
that the second instance received in its <tt>argv</tt> parameter
for the <tt>my_main()</tt> function. The number of arguments <strong>will not</strong>
be provided though. Also, remember that objects given to callbacks are only
guaranteed to be valid until the end of your callback.</p>

<p>If you specify a unique instance and another application with the same name
already exists, the <tt>SIT_CreateWidget()</tt> function will return <tt class="o">NULL</tt>.
This is usually the only time where the return code is worth checking, and if
it fails, you simply have to exit from the function using a <tt><span class="k">return</span>
<span class="o">0</span>;</tt> statement.</p>

<p>Also note that whether or not you catch the event, this library <strong>will not</strong>
activate any of your windows. It will be your duty to either bring to front one of
your application's window, or notify the user that a dialog requires its attention,
like by setting the <tt>SIT_DialogState</tt> property to <tt>SITV_Flashing</tt> on
the corresponding dialog (this effect can also be achieved by opening a modal
dialog as a child of the dialog you want to draw the attention).</p>

<p>At last, use this feature wisely, where it makes sense. Don't try to play
the control freak believing this is a DRM scheme, or worse, creeping features
just for the sake of it.</p>

<h3>SIT_DIALOG</h3>

<p>Dialogs are top level windows intended to receive controls in order
to process user input. There are four styles of dialog that can be
specified using the property <tt>SIT_DialogType</tt>:</p>

<div class="imgcaption">
  <img src="images/dialog_standard.png" alt="Standard dialog">
  <span class="caption">Standard dialog<br><tt>SITV_TopLevel</tt></span>
</div>
<div class="imgcaption">
  <img src="images/dialog_standard_noresize.png" alt="Standard dialog without resize border">
  <span class="caption">Fixed size dialog<br><tt>SITV_TopLevel</tt></span>
</div>
<div class="imgcaption">
  <img src="images/dialog_floating.png" alt="Floatting window">
  <span class="caption">Floating window<br><tt>SITV_Floating</tt></span>
</div>
<div class="imgcaption">
  <img src="images/dialog_plain.png" alt="Plain">
  <span class="caption">Plain dialog<br><tt>SITV_Plain</tt></span>
</div>

<p>Moreover top level dialog can be modal or modeless. A modal dialog blocks
all input from its parent, it always remain on top of it and does not appear
in the task bar. Any attempt to interact with the parent dialog will make
the title bar of the modal dialog blink for a brief instant. A modeless dialog
on the other side allows the user to interact freely between all windows in
this mode. A modal dialog is created by specifying <tt>SITV_Modal</tt> as
for the <tt>SIT_DialogType</tt> property.</p>

<p>A similar modal behavior can be specified using <tt>SITV_ModalEvt</tt> as
for the dialog type. The main difference with <tt>SITV_Modal</tt> being that
when calling the function <tt>SIT_ManageWidget()</tt> on such dialog, this
function will only return when the dialog is closed. This is especially useful
to implement prompt-like dialog, without having to deal with asynchronous
callback.</p>

<p>Microsoft Windows does support another windowing paradigm known as
Multiple Document Interface (MDI), where pseudo top-level dialogs are seen as
child of another top-level window. It had its heyday back in the nineties,
but even there it was a bad solution for a real problem: the default window
manager of Windows was not very well suited for handling large numbers of
top-level windows. MDI was one solution for limiting this number, but in our
opinion, a tabbed interface is a much better choice from a user stand-point.
So don't expect to see any support for this kind of dialogs in SIT, they
are considered obsolete.</p>

<p>A few more styles are available though the <tt>SIT_Styles</tt> property,
by using the following values that can be OR'ed together:</p>

<dl>
  <dt><tt>SITV_HasResize</tt></dt>
  <dd><img src="images/SITV_HasResize.png" alt="HasResize effect" style="float: left; margin-right:5px">
  This style might be useful to give a hint to the user that your dialog
  is resizable and if you do not want to use a full status bar (which takes
  some vertical space). The resize handle will always be placed in the
  bottom right corner of the dialog. Usually avoid placing controls over
  a square of 10x10px in this corner.</dd>

  <dt style="clear: left"><tt>SITV_NoResize</tt></dt>
  <dd>Somewhat mutually exclusive with the previous style. It will make the
  borders of your dialog smaller (like in the second screenshot above) and
  maximize button will be disabled, to indicate that it cannot be resized
  manually (but can be resized programatically). Mouse cursor won't change
  its shape while hovering the edges. Any resize handle will have no effects.
  </dd>

  <dt><tt>SITV_NoActivate</tt></dt>
  <dd>Usually only meaningful with <tt>SITV_Plain</tt> dialog type. This can
  be used to display a popup, while keeping the focus on the parent dialog.
  If the popup is short-lived, it will avoid that annoying "flash" effect due
  to the brief instant the parent dialog will lose the focus. The popup
  can still be activated programatically using <tt>SIT_SetFocus()</tt>.</dd>

  <dt><tt>SITV_DropShadow</tt></dt>
  <dd><img src="images/SITV_DropShadow.png" alt="DropShadow effect" style="float: left; margin-right:5px">
  Also intended for <tt>SITV_Plain</tt> dialog type. It will draw a shadow
  below the dialog to highlight its z-order, like a menu. Only available on
  Windows XP or later.</dd>

  <dt style="clear: left" id="SITV_DoubleBuffer"><tt>SITV_DoubleBuffer</tt></dt>
  <dd>Enable double-buffering when repainting the dialog. This usually
  eliminates all the flickering when redrawing some controls, especially
  when the dialog is being resized, at the cost of using a little bit more
  memory and CPU. Also when setting this style, keep in
  mind that <strong>whenever you get a device context outside the
  repainting cycle, you'll get a reference on the off-screen buffer</strong>.
  That means the only place you can draw on a double-buffered dialog is
  in your callback associated with the <tt>SITE_OnPaint</tt> event,
  <strong>and nowhere else</strong>. This is usually not a problem,
  because if your application is correctly designed, all rendering should
  already be done in this event. Has no effect on Windows 2000.</dd>
</dl>

<p>Also take note that depending on dialog style and current theme, the window
manager might <strong>not</strong> honor the width you ask (directly or
indirectly through constraints). Remember that system buttons have to be
visible. Minimize, maximize and close boxes, plus system menu take about
100 pixels, so if you want something smaller, you'll to remove some buttons
or even the whole caption bar.</p>

<p id="dialogSize">At last, dialog can have a top-level menu strip, using the property
<tt>SIT_Menu</tt>. This will be discussed more in detail in the next
chapter. Please note that when getting dialog size through
<a href="#manualgeom">dedicated</a> properties, they will only include
client size:</p>

<img src="images/DialogSize.png" alt="Properties effect/value on dialog">

<p>As you can see, neither the menu bar, nor the status bar and of course
not the window's border (known as the non-client area) will be taken into account
when getting the value of the <tt>SIT_Height</tt> or <tt>SIT_Width</tt>
properties. The values stored in the <tt>SIT_Rect</tt> group are setup
so that if you retrieve them, you can set them later (using
<tt>SIT_SetValues()</tt> for example) and be guaranteed that dialog size
and/or position will be exactly like when you retrieve the properties.</p>

<div class="sep"></div>

<p>Dialogs may have a customized icon in their top left corner, used to pull down
the system menu. To do so, you can use the <tt>SIT_IconImage</tt> property and
provide it with either a bitmap (loaded using <tt><a href="#loadbmp">GFX_LoadImage()</a></tt>,
or a <a href="#resfmt">resource</a> identifying an icon (and not a bitmap).</p>

<p>If you use a bitmap, it must be 32bit per pixel, i.e.: RGB with 8bit alpha
channel. If you want to use colormap with single color transparency, you'll have
to use a resource instead. A copy of the bitmap will be made (resource will be
loaded on demand), you can free the original once you dialog is displayed. If you
are planning to use the same icon on several dialogs, you can reuse the memory
allocated for the icon, by providing the same pointer for every dialogs (or the
same resource id).</p>

<p>Icons (ICO format) are preferred because they can embed different sizes, that
can be choosen from depending on the context. Whatever bitmap format you
choose, be sure to provide at least a 32x32px size (although the dialog's icon 
is usually 16x16px, the icon in the alt-tab dialog is at least 32x32px). In any
case the image must be less than 256x256px, although hi-res only bitmap are usually
poorly rendered by Windows prior to Vista. Also, the image does not necessarily
need to be square.</p>

<p>If you do not specify anything for this property, the library will attempt to
load the icon with the ID 1 from the resource segment (usually this is the
application's icon). Here's a few examples on how to use this property:</p>
<pre><span class="c">// Set icon using an external bitmap</span>
Image icon = GFX_LoadImage(<span class="o">"bitmap/appicon.png"</span>);
SIT_SetValues(dialog, SIT_IconImage, icon, <span class="o">NULL</span>);
GFX_FreeImage(icon);

<span class="c">// This loads an icon from resource segment</span>
SIT_SetValues(dialog, SIT_IconImage, (Image)1, <span class="o">NULL</span>);
</pre>

<div class="sep"></div>

<p>Dialogs fire a variety of events. Some were described in the previous
section and does not required much information, except to know
whether or not they are supported by this widget. This includes:
<a href="#SITE_OnClose"><tt>SITE_OnClose</tt></a>,
<a href="#SITE_OnFocus"><tt>SITE_OnFocus</tt></a>,
<a href="#SITE_OnFocus"><tt>SITE_OnBlur</tt></a>,
<a href="#SITE_OnFinalize"><tt>SITE_OnFinalize</tt></a>,
<a href="#SITE_OnResize"><tt>SITE_OnResize</tt></a> and
<a href="#SITE_OnUser"><tt>SITE_OnUser</tt></a>. Some others will be explained
when talking about canvas:
<a href="#SITE_OnClick"><tt>SITE_OnClick</tt></a>,
<a href="#SITE_OnMouseMove"><tt>SITE_OnMouseMove</tt></a> and
<a href="#SITE_OnPaint"><tt>SITE_OnPaint</tt></a>.
A few more are supported, and will require more details:</p>

<ul>
  <li id="SITE_OnRawKey"><tt>SITE_OnRawKey</tt>, <tt>SITE_OnVanillaKey</tt>:
  like said, in the previous chapter, <tt>call_data</tt> will point to a
  <tt>SIT_OnKey</tt> structure. Its definition is:
  <pre style="margin: 10px 0"><span class="t">typedef struct</span>
{
    <span class="t">int</span>  keycode;  <span class="c">/* Unicode code point [1 - 0x10FFFF] */</span>
    <span class="t">int</span>  flags;    <span class="c">/* SITK_Flag* */</span>
    <span class="t">char</span> utf8[<span class="o">6</span>];
}   SIT_OnKey;</pre>

  <p><tt>utf8</tt> field will be valid only for <tt>SITE_OnVanillaKey</tt> event,
  it is a null-terminated string representing the character being produced by
  the combination of key pressed. <tt>flags</tt> are the qualifier (shift,
  control, alt, ...) that have been held while generating the event.
  <tt>keycode</tt> is either the unicode code point for a vanilla key or one
  of the <tt>SITK_*</tt> enumeration for a raw key report (because obviously
  there is no unicode code point for such keys).</p>

  <p>Both events are subject to the auto-repeat feature, i.e: after holding a
  key for a while, you'll get repeated events at interval defined in the control
  panel.</p>

  <p>Keyboard events are targetted to the current control that has the focus.
  If one of your child control has the focus, your dialog <strong>will not</strong>
  receive any event. Moreover, if you <tt class="k">return</tt> <tt class="o">1</tt>
  in any of your keyboard callback, it will prevent any default action related
  to the dialog, like cursor or tab keys for control navigation,
  <span class="shortcut">Esc</span> or <span class="shortcut">Return</span> for activating
  default push buttons. Take note that this does not include menu accelerators
  that are processed way before the event is being dispatched.</p>
  </li>

  <li><tt>SITE_OnCtxMenu</tt>: this event is fired when it is the right time to
  display a popup within the control where the callback is attached. The
  <tt>call_data</tt> parameter will be an array of 2 ULONGs that can be given
  to <tt>SIT_PopupMenu()</tt>.
  </li>
</ul>

<h3 id="SIT_LABEL">SIT_LABEL</h3>

<p>Labels are usually text that can be slightly styled:</p>

<div class="imgcaption">
  <img src="images/SIT_LABEL.png" alt="Default label">
  <span class="caption">Label</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_LABEL_MNEMO.png" alt="Label">
  <span class="caption">Label with mnemonic</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_Foreground.png" alt="Color">
  <span class="caption">Colored label</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_ElipsisRight.png" alt="Elipsis">
  <span class="caption">Elipsis</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_HTMLLink.png" alt="Link">
  <span class="caption">Embedded HTML link</span>
</div>
<div class="imgcaption">
  <img src="images/DisabledLabel.png" alt="Disabled">
  <span class="caption">Disabled label</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_LabelRaisedThick.png" alt="With frame">
  <span class="caption">Thick frame</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_EtchedHoriz.png" alt="Horizontal rule">
  <span class="caption">Separator</span>
</div>

<p>Labels are very simple controls, not much user interaction can be done with
them. By default, label will be sized so that the entire content is visible,
unwrapped. This is not always desirable, when you have a very long phrase that
you want word-wrapped, so that dialog's width remain within tolerable bounds.
To avoid stretching the dialog too much, you can set the width of your label,
using the <tt>SIT_Width</tt> property, the layout manager will be then be able
to compute the optimal number of lines required to display the label unclipped.
Note that the opposite does not work: setting the height to compute the
optimal width.</p>

<p>The optimal height is actually a constraint that will be enforced for you.
This can lead to some side effects, especially when resizing a dialog. Consider
the following example:</p>

<div class="imgcaption">
  <img src="images/UserCreationExample.png" alt="" style="border: 1px solid black">
  <span class="caption">A typical user management window</span>
</div>

<div class="imgcaption">
  <img src="images/UserCreationExampleSmaller.png" alt="" style="border: 1px solid black">
  <span class="caption">The same dialog, resized smaller</span>
</div>

<p>Control constraints have been setup so that this dialog can be resized
horizontally, but not vertically. Have a particular attention to the label
sitting at the bottom right corner of the group box. A yellow background
has been added to see more clearly what's going on, especially when the dialog
will be resized. In this case, when you try to make this dialog horizontally
smaller, there will be a point where the multi-line label cannot be rendered
unclipped using only two lines. That means the label's height have to be
adjusted in order to compensate for the constrained width.</p>

<p>There is two possibilities: either the dialog can also be resized vertically,
or it cannot be. If it cannot, like in the example above, the dialog will be
enlarged for you by the layout manager. If it can, the control that acts as a
buffer to accomodate the height, will be adjusted to make room for the label.
To enable this behaviour, you'll have to explicitely set the label's initial
width through the property <tt>SIT_Width</tt> (otherwise the initial size of the
label will be set so that its entire content is rendered unclipped and unwrapped).
To allow the label to be resized smaller than this initial value, you'll also
have to specify a value for the <tt>SIT_MinWidth</tt> property. Other than that,
nothing more is required.</p>

<div class="sep"></div>

<p>Labels can include mnemonics, as a hint for the user to know which key to
press in order to <em>activate</em> the control immediately following the
label. By following, it is the control that has a tab order immediately
greater than the label (<tt>SIT_TabOrder</tt>). Mnemonics are specified
by prefixing the character you want to highlight by <tt>&amp;</tt> (so, if
you want to include a <tt>&amp;</tt> character in your label, remember to
prefix it by another <tt>&amp;</tt>). By default mnemonics are not displayed,
they will be only after the first key has been pressed.</p>

<p>Starting with Windows XP and onward, labels can include HTML link, although
you'll have explicitely indicate that you want the anchor tags be processed,
by setting the <tt>SIT_HTMLLink</tt> to <tt class="o">True</tt>. You can catch
link activation and preventing default action (starting the default browser on
the URL specified in the <tt>href</tt> attribute), by registering a
<tt>SITE_OnActivate</tt> callback. In that case, the <tt>call_data</tt> will
be the number of the link being clicked (links are numbered from 0 to n-1, where
n = number of links in your string). Don't forget to return 1 to prevent default
action.<p>

<h3 id="SIT_PUSHBUTTON">SIT_PUSHBUTTON</h3>

<p>Push buttons include everything that looks like a button:</p>

<div class="imgcaption">
  <img src="images/PushButton.png" alt="Push button">
  <span class="caption">Push button</span>
</div>
<div class="imgcaption">
  <img src="images/PushButtonDefault.png" alt="Default push button">
  <span class="caption">Default button</span>
</div>
<div class="imgcaption">
  <img src="images/PushButtonWithIcon.png" alt="Button with icon">
  <span class="caption">With icon</span>
</div>
<div class="imgcaption">
  <img src="images/ToggleWithPopup.png" alt="Split-button like">
  <span class="caption">Toggle with icon</span>
</div>
<div class="imgcaption">
  <img src="images/PushButtonIconOnly.png" alt="Icon only">
  <span class="caption">Icon only</span>
</div>
<div class="imgcaption">
  <img src="images/PushButtonDisabled.png" alt="Disabled button">
  <span class="caption">Disabled button</span>
</div>
<div class="imgcaption">
  <img src="images/CheckBox.png" alt="Check box">
  <span class="caption">Check box</span>
</div>
<div class="imgcaption">
  <img src="images/RadioButton.png" alt="Radio button">
  <span class="caption">Radio buttons</span>
</div>

<p>Push buttons are divided into 3 groups:</p>
<ol>
  <li><strong>Action button</strong>: to allow user to perform immediate actions.</li>
  <li><strong>Check box</strong>: to enable the selection of any combination of a given set
  of options.</li>
  <li><strong>Radio button</strong>: to select one choice among a mutually exclusive set.
  Semantically similar to the ComboBox.</li>
</ol>

<p>The button type is controlled through the <tt>SIT_ButtonType</tt> property,
which can only be set at creation time, using one of the following values:</p>

<ul>
  <li><tt>SITV_ActionButton</tt>: this is the default type, usually omitted,
  but given for completeness.</li>

  <li><tt>SITV_CancelButton</tt>: like <tt>ActionButton</tt>, but will also send
  an <tt>OnActivate</tt> event when pressing the <span class="shortcut">ESC</span>
  key.</li>

  <li><tt>SITV_DefaultButton</tt>: similar to <tt>CancelButton</tt>, it will
  send an <tt>OnActivate</tt> event when pressing the
  <span class="shortcut">Enter</span> key and will usually be highlighted with
  a wider border.</li>

  <li><tt>SITV_CheckBox</tt>: a checkmark-able box with a label on its right.</li>
  <li><tt>SITV_3StateCB</tt>: similar to <tt>CheckBox</tt>, but instead of
  toggling between checked/unchecked state, this one cycle through checked,
  unchecked and indeterminate state. A common use-case is to indicate that for
  a given set of items, the option described by the checkbox is not set on
  every items (but at least on one).</li>

  <li><tt>SITV_RadioButton</tt>: semantically very similar to a read-only
  combobox (drop-down list). Using one or the other is a matter of taste
  and/or space available on the interface. If the list of options is short
  it can be useful to display them as radio buttons, as they require less
  mouse gestures.</li>

  <li><tt>SITV_ToggleButton</tt>: it behaves like a checkbox, but has the
  appearance of an action button. Strongly advised to limit its use for a
  fancy mean to display a popup menu. you can programmatically control the
  state of the button using the <tt>SIT_CheckState</tt> property.
  Consider using a toolbar though.</li>
</ul>

<p>On Windows XP and onward, any type of action button can have an icon to be
displayed within the button. This is handled through 3 dedicated properties:</p>

<ul>
  <li><tt>SIT_IconPath</tt> (<tt class="t">STRPTR</tt>) or
      <tt>SIT_IconImage</tt> (<tt class="t">Image</tt>): The path of an image,
  or the image itself.
  See <tt><a href="#loadbmp">GFX_LoadImage()</a></tt> discussion for supported format (briefly: BMP,
  PNG and JPEG, through external files, resource fork or inline blob). Remember
  to encode the path using UTF-8 encoding. Also if your image is not perfectly
  square, it is strongly advised to use 32bpp bitmap with 8bit alpha channel, so
  that transparent parts will adapt gracefully on any theme setting. In case you
  directly gave a reference to a valid image, a copy will be made and it will
  be your duty to free the original.</li>
  <li><tt>SIT_IconOrient</tt> (<tt class="t">enum</tt>): In which side of the
  button the icon will be located (by default it is <tt>SITV_IconOrientLeft</tt>,
  can also be right, top, bottom or center).</li>
  <li><tt>SIT_IconMargin</tt> (<tt class="t">int</tt>): the distance between the
  icon and the button's text.</li>
</ul>

<div class="sep"></div>

<p>Check boxed buttons toggle between the checked and unchecked state (or cycle
through those states plus an indeterminate one when using a tri-state button). By
default label is on the right. If you want to put it on the left, set the
<tt>SIT_AlignHoriz</tt> property to <tt>SITV_AlignRight</tt> (or in a more
mnemotechnical way, the box will be set in the far-most direction described
by the property, with the label being aligned in the same direction). The
checkmark in the box is controlled through the <tt>SIT_CheckState</tt>
property.</p>

<p>Radio buttons behave similarly to check box, there is only one more property
to define into which set the button belong. Only one button in a given set can
be "checked", this policy will be enforced for you, simply specify the set
number using the <tt>SIT_RadioGroup</tt> property (<tt class="t">int</tt>).
Take note that groups are only valid within one level of a hierarchy (i.e: if
you put a group of radio buttons with a group id of 0 as immediate children of
a dialog, and another group with the same id as children of a group box, the
library will consider this as two independent groups). For consistency when
the focus is driven by keyboard, it is advised that no other controls have a
<tt>SIT_TabOrder</tt> value that fall between minimum and maximum tab order
of the group of radio buttons. Also, when creating your radio buttons, don't
forget to specify which one is checked, otherwise all will remain unchecked.</p>

<p>To know which radio button in a group is selected, you can either scan the
<tt>SIT_CheckState</tt> property for every buttons in this group (which is
rather tedious with lots of buttons), or you can get some help from this library.
There is 2 properties you might be interested in:</p>

<ul>
  <li><tt>SIT_CurValue</tt> (<tt class="t">int *</tt>): this property expect
  a pointer to an integer, that has to stay valid as long as the button is managed.
  The library will store the radio button ID that is currently selected in this
  integer. For this to work, you obviously have to set the <b>same</b> reference
  to <b>every buttons</b> in the group, and not just one of them.<br>
  <strong>Note</strong>: this also work with checkbox buttons, although the
  state (0, 1 or 2) of the checkbox will be stored, not the <tt>RadioID</tt>.</li>

  <li><tt>SIT_RadioID</tt> (<tt class="t">int</tt>): this is the value you want
  to store in the reference set using the previous attribute. If you do not set
  this property, a default one will be chosen for you: it is the ordinal
  position of the button within the group, starting at 0.

  <p>Note that the radio button whose <tt>RadioID</tt> match the value currently
  stored in the <tt>CurValue</tt> pointer, will be checked automatically, you
  don't have to manually set the <tt>CheckState</tt> property.</p>

  <p>As a permitted hack, you can suffix the name by a : (colon), followed by
  an integer, which will be used as the <tt>RadioID</tt> value. This part
  (following and including the colon) will then be cut off from the name (note:
  <tt>SIT_Title</tt> must also be set for this to work).</p></li>
</ul>

<div class="sep"></div>

<p>Button activation/state change is notified through the <tt>SITE_OnActivate</tt>
event. The <tt>call_data</tt> for checkbox and radio button will actually be an
integer indicating the state of the button: unchecked (<tt class="o">0</tt>),
checked (<tt class="o">1</tt>) or indeterminate (<tt class="o">2</tt>) for
tri-state checkboxes). For bi-level checkbox, you can see the state as a boolean,
for a tri-state it is advised to use dedicated enumeration. Note that radio buttons
that got automatically unchecked in the set won't get any event notification.</p>

<p>Also take note that setting programmatically the property <tt>SIT_CheckState</tt>
on radio buttons or check boxes <strong>will not</strong> trigger your event handler.
Mutual exclusivity policy will still be enforced on radio buttons though.</p>

<div class="bgtip" style="width: 50%; margin: auto"><p class="tip"><b>Caveat:</b>
buttons also respond to <tt>SITE_OnClick</tt> event. This is usually <strong>NOT</strong>
what you want, since this event is fired as soon as the button is pressed.</p></div>

<h3 id="SIT_FRAME">SIT_FRAME</h3>

<p>Frame or group box are a way to organize your controls to help users recognize
related features. It can be seen as a label with an etched border:</p>

<div class="imgcaption">
  <img src="images/SIT_FRAME.png" alt="Group box">
  <span class="caption">Frame</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_FRAME_Nested.png" alt="Nested group boxes">
  <span class="caption">Nested frames</span>
</div>

<p>Frames are one of the few controls that act as container for other controls,
they can be given as <tt>parent</tt> parameter of the <tt>SIT_CreateWidget()</tt>
function. They behave exactly as dialogs in terms of geometry management, they
can be seen as dialog within the dialog: the <tt>SIT_Margins</tt> related
properties applies, <tt>SITV_AttachForm</tt> attachment is relative to frame's
border (and not the dialog), and unless explicitely set, their size will be set
so that all controls within the frame are visible.</p>

<p>The frame widget has no specific properties and fire no events. Margins will
be set so that they will leave about 5 pixels from each borders, which might be a
little tight. Also take note that border itself is about 3 pixels wide (it depends
on theme setting, but does not vary that much). Although discouraged, remember
that margins can be overridden using negative offset for <tt>SITV_AttachForm</tt>.</p>

<h3 id="SIT_EDITBOX">SIT_EDITBOX</h3>

<p>Edit box typically allows user to enter any form of text:</p>

<div class="imgcaption">
  <img src="images/SIT_EDITBOX.png" alt="Plain edit box">
  <span class="caption">Edit box</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_BorderlessEditColors.png" alt="Borderless">
  <span class="caption">Borderless</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_PlaceHolder.png" alt="Placeholder">
  <span class="caption">With placeholder</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_Password.png" alt="Password">
  <span class="caption">Protected entry</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_Integer.png" alt="Integer">
  <span class="caption">Integer only</span>
</div>
<div class="imgcaption">
  <img src="images/SITV_HotKey.png" alt="Hot key">
  <span class="caption">Shortcut editor</span>
</div>

<p>Text boxes are divided into 3 main categories:</p>
<ol>
  <li><strong>Text input</strong>: using single line, multi-line or password input.</li>
  <li><strong>Integer</strong>: will include a spin control to browse through numbers.</li>
  <li><strong>Shortcut</strong>: allow user to select of combination of key press.</li>
</ol>

<p>This is controlled through the property <tt>SIT_EditType</tt>, which can be assigned
to the following values:</p>

<ul>
  <li><tt>SITV_Password</tt>: will display bullet in place of what user will type.
  Attempting to copy the content will throw an error message.
  This is actually a <strong>very weak</strong> protection, since it is
  possible for external tools to remove the style that makes the bullets appear
  in place of the actual text. Rule of the thumb: keep data in those edit fields
  as short-lived as possible.</li>

  <li><tt>SITV_MultiLineEdit</tt>: like a standard edit box, but will allow the
  user to enter multiple line of text, wrapping the content if it has reached the
  right margin. Note that it has no special formatting capabilities and its
  performance become quite abysmal for text larger than 64Kb, and nearly unusable
  with text over 1Mb. <tt>notepad.exe</tt>
  is based on this kind of control, so you can get a pretty good overview of
  how it sucks, even on Windows 7 as far as it has been tested. Programming
  interface for this type of control has been kept minimal, because they suck
  for anything but the most trivial task.</li>

  <li><tt>SITV_Integer</tt>: a text box that include a spin control on its right
  side. The edit does not forbid non-digit characters. If you really want to, you'll
  have to catch <tt>SITE_OnChange</tt> notifications.</li>

  <li><tt>SITV_HotKey</tt>: allow user to enter a combination of key-stroke.
  Notification events will include the virtual key codes flags (<tt>SITK_*</tt>)
  instead of the actual text of the shortcut. Keep in mind that <strong>every</strong>
  key presses will be catched by this control: tab, enter, escape, cursor keys, with or
  without modifier. Virtual key codes will be discussed more in detail in the
  <a href="#SIT_CANVAS">SIT_CANVAS</a> section.</li>

  <li><tt>SITV_BorderlessEdit</tt>: like a standard single-line edit box, but
  without border and without margin. If set to the same color than the parent
  control, with the <tt>SIT_ReadOnly</tt> property set to <tt>True</tt>, you
  can create some sort of selectable label.</li>
</ul>

<p>As you can see, there is no enumeration value for standard single-line text
box: you simply does not set this property to create such kind of control (since
this property cannot be changed once control has been created). Depending on the
control type you created, different kind of properties will be available. Here
are some explanations for the one that requires more than one phrase to explain:</p>

<dl>
  <dt><tt>SIT_Title</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>Just to be sure it has been said at least once: for all type of controls
  except HotKey, the title property is used to set the content of the edit box,
  including multi-line. Keep in mind that caret position will be reset to 0 when
  setting this property.</dd>

  <dt><tt>SIT_HotKey</tt> (<tt class="t">int</tt>)</dt>
  <dd>This property is used to set or get the "text" within HotKey control type.
  It is a combination of <tt>SITK_*</tt> flags. For example:
  <tt>SITK_FlagCtrl + SITK_FlagShift + <span class='o'>'A'</span></tt>,
  will set the current hot key to <tt>CTRL + MAJ + A</tt> (French locale). Also,
  be careful to not confuse this property with the enumeration <tt>SITV_HotKey</tt>,
  used by the property <tt>SIT_EditType</tt>.</dd>

  <dt><tt>SIT_StartSel</tt>, <tt>SIT_EndSel</tt> (<tt class="t">int</tt>)</dt>
  <dd>Apply for all kind of control but HotKey type. They allow you to set
  the caret (if you specify only one of them) or the part of text being selected
  (if you specify both, with different values). If you select text, the position
  of the caret will always be the greatest of the two integers.
  Also keep in mind that both arguments must specify the <strong>number of
  character</strong> you want to put the selection and/or caret. As a permitted
  hack, if you specify negative values, it will be the number of bytes. Also,
  if you specify out of range values, they will be clipped to the length of
  current text.</dd>

  <dt><tt>SIT_ScrollPos</tt> (<tt class="t">int *</tt>)</dt>
  <dd>This one is only meaningful for Integer type. Its argument must be a pointer
  to a <strong>valid reference</strong> to an integer. The current value
  represented by the control will be stored at the location pointed by this
  reference. Also, do not give a reference to a local variable, it will corrupt
  your stack.</dd>

  <dt><tt>SIT_PlaceHolder</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>This property is valid for any kind of text entry, except HotKey. It will
  display a grayed text over the box if nothing is entered by the user yet.
  Only available on common control v6 (XP with theme enabled).</dd>

  <dt><tt>SIT_BuddyEdit</tt> (<tt class="t">SIT_Widget</tt>)</dt>
  <dd>An edit control can be linked with a slider. Linked controls will update
  each other as the user or the program itself interact with one of the two controls.
  A slider is usually a quick way to have a gross estimation of the number
  the user wants. If more precision is desired, the user can then use the edit (usually
  an integer kind, but nothing prevent you from using a plain text box).</dd>

  <dt><tt>SIT_TempEdit</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Default behavior for Win32 edit class is to keep the focus even if you
  click outside the control's area, which might be annoying if you want to do
  some kind of temporary editing, like Windows Explorer file renaming. If this
  property is set to <tt class="o">True</tt>, any attempt to click outside the
  edit box, will give the focus to the control that has been clicked. You can
  then trap <tt>SITE_OnBlur</tt> on the edit to know when to remove it.</dd>
</dl>

<div class="sep"></div>

<p>There is two events reported by text boxes: <tt>SITE_OnChange</tt> and
<tt>SITE_OnChanged</tt>. Both will provide the content of edit box using a
UTF-8 string as the <tt>call_data</tt> parameter of the callback. The first
one will be sent before any changes on screen have been applied, while the
second will be triggered when changes are already visible. The expected
return code is a boolean, if set to <tt class="o">True</tt>, will mean that
the buffer provided has been modified, and you want the changes to be
displayed. However, you cannot write more than <tt>strlen(call_data)</tt>
in this buffer. If you ever need more, you'll have to set explicitely the
<tt>SIT_Title</tt> property, along with the <tt>SIT_StartPos</tt> and/or
<tt>SIT_EndPos</tt>.</p>

<p>You also might want to catch some keystrokes (like cursor keys, function
keys, ...) while the focus is in the editbox. You can register a
<tt>SITE_OnRawKey</tt> callback, and processed events you might be interested
in. Don't forget to return 1 to signal that you've processed the event and
do not want it to be given to the edit box again. Remember that you can
also register "global" keystroke by using menu. That way the keystroke
will be available anywhere in your window, no matter which control has
the focus.</p>

<p>If you are linking a text box with a slider, it is advised to only set
your callback on one of the controls, otherwise you will get every
notifications twice.</p>

<h3 id="SIT_COMBOBOX">SIT_COMBOBOX</h3>

<p>ComboBox is a way to let the user choose one entry among a list of
choices:</p>

<div class="imgcaption">
  <img src="images/DropDownList.png" alt="Drop down list">
  <span class="caption">Drop down list</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_COMBOBOX.png" alt="ComboBox">
  <span class="caption">ComboBox</span>
</div>

<p>ComboBox has two operating modes: one in which the selected entry is
editable (this is actually what got referred as "ComboBox"), and one where
it is read only (which is usually referred as drop down list). The way to
create one type or another is through the property <tt>SIT_ReadOnly</tt>.</p>

<p>The down arrow button lets you display/hide the list associated with the
control. Depending on your configuration, this list might appear with a
sliding effect, which can become quite annoying once you get familiar with
the application, and expect the application to react in the range of tens of
miliseconds, instead of hundreeds. Unfortunately this can only be disabled
using a system-wide setting (on XP it is buried into My Computer's properties
&#x25BA; Advanced &#x25BA; Performance settings &#x25BA; Visual effects
&#x25BA; uncheck "Slide open combo boxes" (translation can also be funny),
add one or maybe two layers of popup for each new generation of Windows).</p>

<p>To manage items within this list, there is two methods available.
The first method is to use the generic tag/value model, through
the property <tt>SIT_InitialValues</tt>. The expected argument is a
string, encoding the items as a tab (ASCII code 9) separated list, e.g.:
<tt class="o">"First item<span class="s">\t</span>Second item<span class="s">\t</span>Third item"</tt>. This method
is well suited when the number of items is fixed and does not vary
during the lifetime of the ComboBox. If it is not the case, you might
be interested in the second method.</p>

<p>Since generic interface can sometimes be tedious, a few specialized
functions exist:</p>

<dl>
  <dt><tt><span class="t">int</span> SIT_ComboInsertItem(SIT_Widget, <span class="t">int</span> index, STRPTR item, APTR rowtag);</tt></dt>
  <dd>Insert an item at the zero-based index specified (the library will make
  a copy of the string). You can also provide <tt class="o">-1</tt> as the
  index to insert the item at the end of list.
  <tt>rowtag</tt> is an arbitrary pointer you may want to associate with the
  item. Note that this value cannot be set, nor retrieved using the generic
  tag/value interface. The return value will be the index at which the item
  has been inserted, or <tt class="o">-1</tt> in case of error.</dd>

  <dt><tt><span class="t">int</span> SIT_ComboDeleteItem(SIT_Widget, <span class="t">int</span> index);</tt></dt>
  <dd>Remove an item from the list. If <tt>index</tt> is negative or out of
  range, it will delete the last item of the list. Return value is the index
  of the item that has been deleted.</dd>

  <dt id="ComboGetRowTag"><tt>APTR SIT_ComboGetRowTag(SIT_Widget, <span class="t">int</span> nth, STRPTR * label);</tt></dt>
  <dd>Allows you to retrieve the row tag associated with an item. If item
  is negative, it will retrieve the row tag of the currently selected
  item. If <tt>label</tt> is not <tt class="o">NULL</tt>, the text of the
  item will also be stored at the location pointed by <tt>label</tt>. The
  content of this string is read-only, do not modify it. This feature is
  intended for custom drawn ComboBox.</dd>
</dl>

<p>Remember that both methods can be mixed: usually, you initialize the
ComboBox through <tt>SIT_InitialValues</tt>, and then later modify the list
through the specialized functions. Also, setting the property <tt>SIT_InitialValues</tt>
will remove all existing items before inserting the new ones.</p>

<div class="sep"></div>

<p>There is two specific events reported by the ComboBox:</p>
<ul>
  <li><tt>SITE_OnPaint</tt>: This event will let your callback handle items'
  repainting. This might be useful if you want more
  fancy formatting capabilities than simple text. <tt>call_data</tt> will
  be a pointer to a graphic context (<tt>GC</tt>). Use the function
  <a href="#GFX_GetRefresh"><tt>GFX_GetRefresh()</tt></a> to get the rectangle of the item being
  drawn. The entire rectangle must be refreshed, otherwise you might
  see leftover of other window content. You will also need to call
  the <a href="#GFX_GetState"><tt>GFX_GetState()</tt></a> function to get the
  item number to redraw. Be careful, the high order bit indicate
  whether or not the item is selected (whose background is usually
  rendered with the color <tt>GFX_ColorBgHighlight</tt>).
  Then, you can use <a href="#ComboGetRowTag"><tt>SIT_ComboGetRowTag()</tt></a>
  to get item text.</li>
  <li><tt>SITE_OnMenu</tt>: This one is used to report a new item
  being selected in the list. <tt>call_data</tt> can be cast to an
  integer, to get the item number.</li>
</ul>

<h3 id="SIT_LISTBOX">SIT_LISTBOX</h3>

<p>Listbox are a way to display a list using various display formats: report
view, icon view, column list, ... Those who knows a bit of Win32 programming
will recognize that it is based on the list view control and not on the plain
original listbox.</p>

<div class="imgcaption">
  <img src="images/SIT_LISTBOX.png" alt="Listbox with column header">
  <span class="caption">Listbox with column header</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_LISTBOX_Icons.png" alt="Listbox with icons">
  <span class="caption">Listbox with icons, no header</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_LISTBOX_IconView.png" alt="Listbox using icon view">
  <span class="caption">Listbox using icon view</span>
</div>

<p>The first thing you need to be aware when using this control, is even if
you are going to only use the icon view, or the report without any header,
you will still have to create a column. This is usually the first thing you
do with listbox: manage columns. Remember that except report view, all other
view will only display the content of the first column.</p>

<h4>Managing columns (report view)</h4>

<p>There is 3 properties to handle this: <tt>SIT_ColumnNames</tt>,
<tt>SIT_ColumnWidths</tt> and <tt>SIT_ColumnAlign</tt>. Only <tt>ColumnNames</tt>
is mandatory, it is a tab-delimited list of names, e.g:
<tt class="o">"Name<span class="s">\t</span>Address<span class="s">\t</span>Server"</tt>.
It is this property that will defined how many columns your list will have.
<tt>ColumnAlign</tt> is also a tab separated list indicating the alignment
for the given column, among: <tt>L</tt> for left (default), <tt>R</tt> for
right and <tt>C</tt> for center, e.g: <tt class="o">"L<span class="s">\t</span>R<span class="s">\t</span>C"</tt> (a small caveat is that the first column will always
be left-justified, no matter what you specify for this property).
If you give less items than columns, remaining columns will have a left
alignment, and if you give more, remaining items will be ignored.</p>

<p><tt>ColumnWidths</tt> is optional and can be used to constraint the way space
is distributed across columns, and keep it that way even when the listbox is
resized. Obviously this only affects the report view of the listbox.
It is also a tab-separated list of numbers and/or star (<tt>*</tt>). The star
can also optionally be prefixed by a number. If you speficy a number with
no stars following it, the column will be the number of pixels you specify.
If you gave a star instead, the width of the column will be proportional to
width of the listbox and the "weight" of the column. The weight is the number
before the star, or if there is no number, 1 will be assumed.</p>

<p>For example a <tt>ColumnWidths</tt> set to
<tt class="o">"*<span class="s">\t</span>*<span class="s">\t</span>*"</tt>
will set the width of all columns to be of equal width. If you ever make your
listbox resizable, you will see the width of your columns expand
or shrink evenly as you change the width of the list. Now if you specified
a value of <tt class="o">"2*<span class="s">\t</span>*<span class="s">\t</span>*"</tt>
for this property, the first column will have twice the space
of the two remaining columns (the first example above have been set
that way). One thing to keep in mind, is that columns whose width is set
relative to listbox width, can still be resized using column separators.
In that case, the weight of the columns will be adjusted automatically.</p>

<p>One of the advantage of setting this property is that the listbox will
never show a horizontal scrollbar, which is often cumbersome to deal with,
especially if there is already a vertical one.</p>

<p>If you do not set this property, the initial width of your columns, will be
the minimal width to display the label header (and not the list items). The
user will be able to resize the column at will, including enlarging past the
visible width of the list, which will make appear a horizontal scrollbar. When
the list is resized, the columns will keep the width they have.</p>

<p>You can still change various parameters of any columns at runtime, using this
specialized function:</p>

<pre><span class="t">Bool</span> SIT_ListSetColumn(SIT_Widget, <span class="t">int</span> col, <span class="t">int</span> width, <span class="t">int</span> align, <span class="t">STRPTR</span> label);</pre>

<p>Where each parameters have the following meaning:</p>

<ul>
  <li><tt>col</tt>: the 0-based column number you want to alter its properties.</li>
  <li><tt>width</tt>: the new width of the column. You can also use the special
  value <tt>DontChange</tt> to let the width of the column as it is currently.
  Alternatively, you can also use <tt>AutoArrange</tt> to compute the optimal
  width to display both header and list items. Any numeric value, will set the
  width to the specified number of pixels.</li>
  <li><tt>align</tt>: the alignment for this column: <tt class="o">'L'</tt> for
  left, <tt class="o">'R'</tt> for right, <tt class="o">'C'</tt> for center and
  <tt>DontChange</tt> to leave the alignment as it is.</li>
  <li><tt>label</tt>: the new label for the column or <tt>DontChangePtr</tt> to
  leave it as it is.</li>
</ul>

<p>You can also use the dedicated properties, but attributes for all columns
will have to be specified in one <tt>SIT_SetValues()</tt> call.</p>

<h4>Managing items</h4>

<p>Items are managed through dedicated functions. First, there is one function to
insert items in the list:</p>

<pre><span class="t">int</span> SIT_ListInsertItem(SIT_Widget w, <span class="t">int</span> row, <span class="t">APTR</span> image, <span class="t">APTR</span> rowTag, ...);</pre>

<p>Each parameter have the following meaning:</p>

<ul>
  <li><tt>row</tt>: 0-based index where you want to insert your row. Use a
  negative number to insert at the end of the list.</li>

  <li><tt>image</tt>: a bitmap load by a call to <tt><a href="#loadbmp">GFX_LoadImage()</a></tt> or
  derivative. Each inserted image has a number assigned to it, although you'll
  have to use another function to get it (see below). Once you get it, you can
  use this number for this parameter in order to reuse bitmaps. <strong>Also a copy of
  the image you provide will be made</strong>, you'll have to manage the life
  cycle of the copy you provided.
  
  <p>Set this parameter to NULL to not display any icon with the item. If you
  set an icon for at least one item, a space set to the size of the <strong>first</strong>
  icon you added will be reserved in the first column. Remember to scale all
  your icons that might come after according to the first one.</p>

  <p>As a possible hack, you can use this icon to change the
  default row height, which will be set to norrowly fit the font height.
  If you want more space, you can add a 1px wide and whatever high image on
  <strong>one</strong> item, and all the other will use the same spacing.
  The image must not be completely blank though, set it at least with
  <tt>RGBA(0, 0, 0, 1)</tt>.</p>

  <p>The first icon will also determine the color depth of following icons.
  If you use 24bpp for the first one, all the others will be converted to this
  format. Also if you provide 24bpp images, the listbox will use a dithered
  pattern for the icon selection overlay. By providing 32bpp images, the overlay
  will be an alpha-shaded solid color.</p>

  <p>Also report view uses a separate set of icon from all other view modes.
  TBD</p>
  </li>

  <li><tt>rowTag</tt>: an arbitrary pointer you may want to associate with the
  item.</li>

  <li><tt>...</tt>: NULL-terminated list of strings, one for each column. This
  function will only read your arguments up to the number of columns there is in
  the listbox, so as a permitted shortcut, you can omit the NULL if you gave the
  same number of strings than there are columns.</li>
</ul>

<p>To delete one row, you can use the following function:</p>

<pre><span class="t">void</span> SIT_ListDeleteRow(SIT_Widget w, <span class="t">int</span> row);</pre>

<p><tt>row</tt> is the 0-based index of the row you want to delete. You can use
the special value <tt class="o">-1</tt> as a mean to delete all rows from the
listbox.</p>

<p>To modify a cell of the listbox, there the following function:</p>

<pre><span class="t">void</span> SIT_ListSetCell(SIT_Widget w, <span class="t">int</span> row, <span class="t">int</span> col, <span class="t">STRPTR</span> text, <span class="t">APTR</span> image, <span class="t">APTR</span> rowTag);</pre>

<p>The following values can be assigned to each parameters:</p>

<ul>
  <li><tt>row</tt>: the 0-based index of the row you want to modify. Use a
  negative value to modify the last item.</li>

  <li><tt>col</tt>: 0-based index of the cell's column you want to set the
  text. This parameter is only meaningful if you are going to change the
  text of the cell. Otherwise, the value given for this parameter will be
  ignored.</li>

  <li><tt>text</tt>: label to set the targetted cell. You can use the
  special value <tt>DontChangePtr</tt> to not modify the cell's text,
  which can be useful if you want to alter the others cell properties.</li>

  <li><tt>image</tt>: an image obtained from a prior call to <tt><a href="#loadbmp">GFX_LoadImage()</a></tt>.
  See the discussion for the function <tT>SIT_ListInsertItem()</tt> just above,
  to know what to expect from this parameter. You can use the special value
  <tt>DontChangePtr</tt> to leave the icon state/bitmap as it is. Whatever you'll
  give for the <tt>col</tt> parameter, the icon will always be set on the first
  column.</li>

  <li><tt>rowTag</tt>: the new tag you want to set for the row or <tt>DontChangePtr</tt>
  for leaving this value as it is. As with the <tt>image</tt> parameter, the
  <tt>rowTag</tt> will always be set on the first column, no matter what you
  gave for the column number.</li>
</ul>

<h4>Other properties</h4>

<p>A few more specialized properties exist to help you manage listbox:</p>

<ul>
  <li><tt>SIT_SortColumn</tt> (<tt class="t">int</tt>): allows you to programmatically
  set the column used for sorting items. If the integer is positive or 0, the specified
  column will be used to sort items in ascending order. If the integer is negative, the
  <tt>-n-2</tt> will be sorted in descending order (i.e: to sort first column in
  descending order, specify <tt>-2</tt>).</li>
  <li><tt>SIT_SelectedIndex</tt> (<tt class="t">int</tt>): set or get currently
  selected row or -1 if none are selected. In case of multi-selection is allowed, this
  will give you the index of the last item selected.</li>
  <li><tt>SIT_RowSel(row)</tt> (<tt class="t">int</tt>): set or get selection state
  of a row. If the list is single-selection only, it will automatically deselect the
  previously selected item. This tag is actually a macro, where you have to give the
  0-based row number as argument, like this:
  <pre>SIT_SetValues(list, SIT_RowSel(<span class="o">0</span>), True, <span class="o">NULL</span>);</pre></li>
  <li><tt>SIT_RowTag(row)</tt> (<tt class="t">APTR</tt>): this tag allows you to set
  an arbitrary pointer to the given row. It works like the previous one: you have
  to specify the row you want to modify as argument to the tag name.</li>
</ul>

<h4>Events</h4>

<p>Here is the list of specific events sent by listbox:</p>

<dl>
  <dt><tt>SITE_OnActivate</tt></dt>
  <dd>This event is triggered whenever the user double-click on an item. The
  <tt>call_data</tt> parameter of the callback will be the row (0-based index)
  of the item being activated.</dd>

  <dt><tt>SITE_OnChange</tt> / <tt>SITE_OnChanged</tt></dt>
  <dd>Both events fire the same kind of notification: whenever the selection
  of the listbox <strong>has changed</strong>. As a shortcut, to spare you the
  hassle to remember which one it is, this library will first check if there
  is a <tt>OnChanged</tt> callback registered, if there is nothing, it will
  check for a <tt>OnChange</tt> callback. Be careful tough, to not register
  both events, since only the <tt>OnChanged</tt> will be triggered, no matter
  what your callback will return.
  </dd>

  <dt><tt>SITE_OnPaint</tt></dt>
  <dd><p style="margin-top: 0">This event will give you access to the item
  repainting process. Do not make the mistake to underestimate this task, it
  usually involves a lot of work to do it right. That's why this library allows
  you to handle this task in 2 ways:</p>
  <ol>
    <li>If you only want to change foreground and/or background color of some
    items, you can set the corresponding colors in the graphics context passed
    as the <tt>call_data</tt> parameter. You'll have to <tt class="k">return</tt>
    0 when you exit from callback to tell the library that the repainting cycle
    is not complete and let the system finish the job. Remember that you can also
    use the <tt>SIT_Foreground</tt> and <tt>SIT_Background</tt> property to set the
    color of all your items.</li>

    <li>You handle everything yourself: <tt>GFX_GetStage()</tt> will tell you
    which row, cell and selection state you'll have to handle. Use macros TBD
    to get this information splitted up. Remember that the same callback will
    be used for the repainting of all view modes. You can still return 0, if
    you do not want to handle one particular mode.</li>
  </ol>
  </dd>

  <dt><tt>SITE_OnSortItem</tt></dt>
  <dd>This one is triggered whenever two items have to be compared. The <tt>call_data</tt>
  parameter is a pointer to a <tt>SIT_OnSort</tt> structure, which is declared like this:
  <pre><span class="t">typedef struct</span>
{
	<span class="t">APTR</span> item1;
	<span class="t">APTR</span> item2;
	<span class="t">int</span>  column;
} SIT_OnSort;</pre>
  <p>Where each field will be initialized the following way:</p>
  <ul>
    <li><tt>item1</tt>, <tt>item2</tt>: the <tt>rowTag</tt> that was given when
    items were inserted.</li>
    <li><tt>column</tt>: the 0-based index of the column to sort.</li>
  </ul>
  <p>The return code of the callback has to be from the following set of enums:</p>
  <ul>
    <li><tt>SIT_SortBefore</tt> (<tt class="o">-1</tt>): <tt>item1</tt> should be before <tt>item2</tt>.</li>
    <li><tt>SIT_SortEqual</tt> (<tt class="o">0</tt>): <tt>item1</tt> is equal to <tt>item2</tt>.</li>
    <li><tt>SIT_SortAfter</tt> (<tt class="o">1</tt>): <tt>item1</tt> should be after <tt>item2</tt>.</li>
    <li><tt>SIT_SortAlpha</tt> (<tt class="o">2</tt>): ask the library to perform a case-insensitive
    lexicographic ordering based on the current text there is in the cells of each item.</li>
    <li><tt>SIT_SortBinary</tt> (<tt class="o">3</tt>): same like <tt>SIT_SortAlpha</tt>, but do not
    take case into consideration.</li>
    <li><tt>SIT_SortNumeric</tt> (<tt class="o">4</tt>): consider the text of each item to be
    decimal integers, and use them to sort the rows.</li>
    <li><tt>SIT_SortAlphaNum</tt> (<tt class="o">5</tt>): mix between alpha and numeric, this sorting
    method is best intended for filenames, where files like these (in lexicographic order):
    <pre>File1.exe     File10.exe      File2.exe     File40.exe    File5.exe</pre>
    Will be sorted like this:
    <pre>File1.exe     File2.exe       File5.exe     File10.exe    File40.exe</pre>
    </li>
  </ul>
  <p>Note: you do not have to handle the ascending/descending order: this will
  be taken care of automatically for you.</p>

  <p>The only caveat when you handle the sorting yourself is to be careful to
  return a value in the range [-1, 1]. That means you cannot use the return
  value of function like <tt>strcmp()</tt>, or return the result of a substraction
  to compare two integers. You'll have to split the comparison to return a specific
  code for each case, using something like this:
  <pre><span class="t">static int</span> OnSortFiles(SIT_Widget w, APTR cd, APTR ud)
{
    SIT_OnSort * sort = cd;
    <span class="t">int</span>          diff = ((FileInfo)sort-&gt;item1)-&gt;ts - ((FileInfo)sort-&gt;item2)-&gt;ts;
    <span class="k">if</span> (diff &lt; <span class="o">0</span>) <span class="k">return</span> -<span class="o">1</span>;
    <span class="k">if</span> (diff &gt; <span class="o">0</span>) <span class="k">return</span>  <span class="o">1</span>;
    <span class="k">return</span> <span class="o">0</span>;
}</pre>
  </p>
  </dd>
</dl>

<h3 id="SIT_CANVAS">SIT_CANVAS</h3>

<p>Canvas is a generic control, where you have to handle all by yourself,
like keyboard, mouse and repainting. One visual feature is available, the
possible border around the client area, through the <tt>SIT_FrameStyle</tt>
property:</p>

<div class="imgcaption">
  <img src="images/SITV_Sunken.png" alt="Sunken frame">
  <span class="caption">SITV_Sunken</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_SunkenThick.png" alt="Thick sunken frame">
  <span class="caption">SITV_SunkenThick</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_Raised.png" alt="Raised frame">
  <span class="caption">SITV_Raised</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_RaisedThick.png" alt="Thick raised frame">
  <span class="caption">SITV_RaisedThick</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_Etched.png" alt="Etched frame">
  <span class="caption">SITV_Etched</span>
</div>

<p>Despite having no intrinsic features for the user, this is one of the most
useful control from a programmer stand point. Still, designing something useful
and user-friendly, especially taking into account keyboard and mouse interface,
can be a daunting task even for something as simple as a pushbutton.</p>

<p>Usually the first event handled is the one managing the OnPaint
notifications, because default handler does almost nothing. Without any
graphics on the screen, no user interaction can be made, therefore we'll
first see what to expect from this event.</p>

<h4 id="SITE_OnPaint">Handling <tt>SITE_OnPaint</tt> event</h4>

<p>This is one of the most important event for such kind of widget, since the
default handler only erases the control with its background color. As stated
in the previous section, the <tt>call_data</tt> will be a pointer to a graphic
context, which has to be seen as an opaque pointer: usually the <tt>call_data</tt>
is directly renamed into <tt>gc</tt> and used as is for all graphics-related
functions that ask such pointer. Remember what have been said in
<a href="#chapter7">chapter VII: Events/callbacks</a>: <tt>call_data</tt>
parameter remain the property of this library, do not try to free that object
with <tt>GFX_Free()</tt>. Other than that, what functions are available will
be described in the next chapter, there is a few points to be aware before.</p>

<p>Windows, like many other graphical operating system, does not by default
save what you draw on a window. If another top-level dialog is put in front
of the area you just draw, and then moved away, without further action, the
drawing will be irremediably erased. Hopefully, the system will notify you
whenever part of your area has been erased one way or another: this is the
purpose of the <tt>SITE_OnPaint</tt> event.</p>

<p>A first point to be aware is that the area to refresh in response to an
OnPaint event is usually smaller than the client area of your canvas.
The graphics layer can report the area to refresh in the form of a rectangle,
it is strongly advised to honor this information, by limiting the numbers of
objects to redraw to the ones that are affected by the erasure. It doesn't have
to be pixel-perfect, but at least provide some provision to limit redrawing.</p>

<p>Second, even if the area reported is in the form of a rectangle, the area
to refresh might not be a rectangle. For example, when you have other top-level
dialogs covering partially your area like this:</p>

<div class="imgcaption" style="padding-right: 20px">
  <img src="images/OnPaintRegion.png" alt="Canvas OnPaint region">
  <span class="caption">Canvas covered by two dialogs</span>
</div>

<div class="imgcaption">
  <img src="images/OnPaintClippingArea.png" alt="Area to refresh">
  <span class="caption">Area concerned by refresh (red)</span>
</div>

<div class="imgcaption">
  <img src="images/OnPaintClippingAreaZoom.png" alt="Area to refresh (zoom)">
  <span class="caption">Clipping region enlarged</span>
</div>

<p>If the canvas is ever brought to front, the area that will be marked for
refresh are indicated in red. Although the rectangle reported will covered the
entire client area, any attempt to draw ouside red region will be ignored. This
is actually more than useful, as otherwise you'll have to be extra cautious
when handling redrawing notifications, especially when using alpha-blended
operations, like 32bpp bitmaps or anti-aliassed fonts.</p>

<p>Limiting the area to refresh can become a daunting task depending on the
complexity of the document you try to render. There is a known design pattern
for handling documents that are composed of a discreet set of objects (like a
CAD diagram, a list, ...): you write an iterator that for a given rectangle
gives you all the objets that are included, even partially, in this rectangle.
This iterator will solve at least two problems for you:</p>

<ol>
  <li>You'll be able to limit the objects to refresh when receiving an
  <tt>OnPaint</tt> notification.</li>
  <li>This iterator will also be useful when handling mouse action. Usually,
  it will be able to tell you over which object the user has clicked, or
  perform some kind of hot-tracking.</li>
</ol>

<p>This iterator can be tedious to write, but it is usually well worth the
effort. In the example chapter there are two sample programs that uses two
different approaches to this problem. The <a href="#giv">first</a> uses this
design pattern extensively for two custom controls. The <a href="#sitedit">other</a>
limit the area to refresh directly in the <tt>OnPaint</tt> callback, mainly
because the objects are not that discreet and anyway positions can easily be
evaluated on the fly.</p>

<h4>Flicker-free drawing</h4>

<p>Flicker is likely to occur when the canvas is being resized. The default
behaviour of this control in that case is to clear the entire canvas content
with its background brush, and only after that, you'll get an <tt>OnPaint</tt>
notification. The slight delay between the two operations (clearing and
redrawing) will be enough to create a flickering effect, because there can
be no guarantee to fire both events before the screen got updated.</p>

<p>You have at least two options to avoid this problem:</p>
<ol>
  <li>Use the flag <a href="#SITV_DoubleBuffer">SITV_DoubleBuffer</a> on the dialog containing
  the canvas. This will actually remove almost all flickering effects in your dialog, not just
  on your canvas.</li>

  <li>Set the property <tt>SIT_UserBgClear</tt> of the canvas to <tt class="o">True</tt>
  (it defaults to <tt>False</tt>). The effect of this property is that it <strong>will
  not</strong> clear the background of your canvas whenever it is resized. You'll still
  get <tt>OnPaint</tt> notifications for the entire area. When this property is set to
  True, you'll have to be extra cautious when drawing with operations involving alpha-blend.
  This includes for example painting text with a transparent brush (<tt>GFX_TxtModeTransparent</tt>)
  or 32bpp bitmaps. You'll not be able to draw them directly on the display, because
  there will be something on the screen when you get the <tt>OnPaint</tt> notification.
  Use this property with caution, it is much harder to get it right than it seems.</li>
</ol>

<p>Now that you have something on screen, you can start interacting with
user input.</p>

<h4>Handling mouse events</h4>

<p>Mouse events include mouse click/release (which include mouse wheel) and
mouse movements. Mouse clicks are reported using <tt>SITE_OnClick</tt>
notification, which include any button pressed or released, mouse movement are
notified by <tt>SITE_OnMouseMove</tt>. It not that unusual to use the same
callback for both events, especially since they use the same datatype for the
<tt>call_data</tt> parameter: a pointer to a <tt>SIT_OnMouse</tt> structure.
It is declared as is:</p>

<pre><span class="t">typedef struct</span>
{
    <span class="t">int</span> button; <span class="c">/* 0 = left, 1 = right, 2 = middle, 3 = wheel (state = nb of lines) */</span>
    <span class="t">int</span> state;  <span class="c">/* SITOM_* */</span>
    <span class="t">int</span> x, y;
    <span class="t">int</span> flags;  <span class="c">/* SITK_Flag* */</span>
}   SIT_OnMouse;</pre>

<p><tt>button</tt>, <tt>x</tt> and <tt>y</tt> are pretty straightforward,
<tt>flags</tt> is a bitfield to know which qualifiers were held while generating
the mouse event, and <tt>state</tt> can take the following values:</p>

<ul>
  <li><tt>SITOM_ButtonPressed</tt>: the button is being pressed.</li>
  <li><tt>SITOM_ButtonReleased</tt>: the button is released (never reported for
  mouse wheel).</li>
  <li><tt>SITOM_DoubleClick</tt>: reported when user clicks twice over the same area
  in a given amount of time (defined in control panel). This event is always
  preceeded by a <tt>SITOM_ButtonPressed</tt>, <tt>SITOM_ButtonReleased</tt> and
  again a <tt>SITOM_ButtonPressed</tt> event.</li>
  <li><tt>SITOM_Move</tt>, <tt>SITOM_CaptureMove</tt>: two similar events. They
  are fired whenever the mouse has moved. <tt>SITOM_Move</tt> is only reported
  when the mouse is over the control. To get notification outside, you need to
  initiate a captured move.</li>
  <li><tt>SITOM_NextPage</tt>, <tt>SITOM_PrevPage</tt>: those ones are special
  values for mouse wheel. Mouse setting within control panel can define that
  whenever the mouse wheel is moved, a whole page should to be scrolled. It is
  up to you to honor this setting.</li>
</ul>

<p>To initiate a captured move in order to get mouse move notifications outside
widget bounding box, you need to return a positive integer from your callback,
and only in response to mouse button press (return code will be ignored for
any other type).</p>

<p>As stated in the comment, <tt>state</tt> field will report the number of
lines to scroll when <tt>button</tt> field is set to 3 (default value from
control panel is usually set to 3). The <tt>state</tt> can also take the
special values <tt>SITOM_NextPage</tt> or <tt>SITOM_PrevPage</tt> to indicate
that a whole page need to be scrolled.</p>

<h4>Handling keyboard</h4>

<p>Keyboard events are reported through <tt>SITE_OnVanillaKey</tt> and
<tt>SITE_OnRawKey</tt> notifications. They were described when talking about
<a href="#SITE_OnRawKey">dialogs</a> and work the same way for canvases,
although the latter provides one more feature that is usually related to
keyboard: <strong>the caret</strong>.</p>

<p>Not to be confused with the mouse cursor, the caret is that blinking
bar/block to indicate where text insertion occurs when using the keyboard.
To handle this, there are 5 properties: 4 are used to manage its position
and dimension, and one is used to control its state. The state is what
will make the caret appear, it is a bitfield that can be set using the
<tt>SIT_CaretState</tt> property and is composed of a combination of the
following values:</p>

<ul>
  <li><tt>SITV_HasCaret</tt>: indicate that you want that the control manages
  a caret for you. It means that caret will automatically be hidden when the
  control lose the focus, and displayed again when it got it back. The caret
  will also blink according to user preferences set in the control panel, the
  only thing you'll have to take care is setting its size/position.</li>
  <li><tt>SITV_CaretVisible</tt>: without this flag, the caret will be hidden.
  This is useful in the repainting cycle. Since the caret is usually drawn
  using a XOR operation, you'll have to hide it before repainting anything on
  the canvas, and display it again once you are done. This can be done like this:
  <pre><span class="t">int</span> my_onpaint(SIT_Widget canvas, <span class="t">APTR</span> gc, <span class="t">APTR</span> ud)
{
    SIT_SetValues(canvas, SIT_CaretState, SITV_HasCaret, <span class="o">NULL</span>);

    <span class="c">/* Handle repainting ... */</span>

    SIT_SetValues(canvas, SIT_CaretState, SITV_HasCaret | SITV_CaretVisible, <span class="o">NULL</span>);

    <span class="k">return</span> <span class="o">1</span>;
}</pre>
  </li>
</ul>

<p>The caret size and position is set through the properties <tt>SIT_CaretX</tt>,
<tt>SIT_CaretY</tt>, <tt>SIT_CaretWidth</tt> and <tt>SIT_CaretHeight</tt>.
Whenever you change any of these properties, the caret will be redrawn for you,
it is not needed to hide it before.</p>

<p>Another feature related to keyboard management is <strong>the focus</strong>.
The focus is the control to which keyboard events will be sent. You can move
this focus using the tab and/or arrows keys. Some controls will "steal" the focus
whenever they are clicked on, like push-buttons, radio, checkboxes, listbox, ...
some do not, like toolbars or canvas. If you ever add a keyboard interface, you
might be interested to enable this behaviour, by setting the
property <tt>SIT_AutoFocus</tt> to <tt class="o">True</tt>. If your canvas also
has a border around it, a focus rectangle will be drawn for you whenever the
canvas receive the focus.</p>

<p>Remember that whenever the whole dialog lose the focus (user activating
another window), if your dialog is activated again later, your canvas will not
receive the focus again (unless the user clicked inside, with auto-focus on).
If you want the focus to remain on the canvas whenever no other controls have
the focus, you might trap the <tt>OnFocus</tt> event for the dialog and use
<tt>SIT_SetFocus()</tt> to force the canvas to be the default control.</p>

<h3 id="SIT_SCROLLBAR">SIT_SCROLLBAR</h3>

<p>Scroll bars are typically required when you want to display a document that
could not fit in a given area. You can then display horizontal and/or vertical
scroll bars along the view to allow the user to jump to other parts of the
document.</p>

<div class="imgcaption">
  <img src="images/SIT_SCROLLBAR.png" alt="Scroll bar">
  <span class="caption">Scroll bar</span>
</div>

<div class="imgcaption">
  <img src="images/ScrollBarDisabled.png" alt="Disbaled scroll bar">
  <span class="caption">Disabled</span>
</div>

<p><strong>Caveat</strong>: to disable a scrollbar using <tt>SIT_Enabled</tt>
property, you must not modify anything related to the thumb, otherwise the
control will be automatically re-enabled.</p>

<p>The following properties control the appearance of the scroll bar:</p>
<dl>
  <dt><tt>SIT_MinValue</tt>, <tt>SIT_MaxValue</tt> (<tt class="t">int</tt>)</dt>
  <dd>Default values for these properties are 0 and 100 respectively. This is the
  range the progress bar will report. Usually, you leave the minimal value alone
  and set the maximum to the total length of your document.</dd>

  <dt><tt>SIT_PageSize</tt> (<tt class="t">int</tt>)</dt>
  <dd>This is the size of the visible part of your document.
  It will define the size of the scroll bar's thumb. Note that values reported
  by the scroll bar, will then be: [<tt>SIT_MinValue</tt> &ndash;
  (<tt>SIT_MaxValue</tt> - <tt>SIT_PageSize</tt> + 1)].</dd>

  <dt><tt>SIT_LineHeight</tt> (<tt class="t">int</tt>)</dt>
  <dd>The amount the thumb will move when clicking on one arrow. Default is 1.</dd>

  <dt><tt>SIT_ScrollPos</tt> (<tt class="t">int</tt>)</dt>
  <dd>The position of the thumb.</dd>
</dl>

<p>Scroll bar can be horizontal or vertical. By default, they are vertical, unless
you set the property <tt>SIT_HorizScroll</tt> to <tt class="o">True</tt>.</p>

<p>The event <tt>SITE_OnScroll</tt> will be fired whenever the position of the
thumb changed. The <tt>call_data</tt> can be cast to an <tt class="t">long</tt>
integer to get thumb's position.</p>

<h3 id="SIT_SLIDER">SIT_SLIDER</h3>

<p>Sliders, like scrollbar, allow the user to choose an integer among a certain
range. But unless scrollbars, which are intended to display the relative size
of a view within a larger part, the purpose of a slider is to point to a
particular integer.</p>

<div class="imgcaption">
  <img src="images/SIT_SLIDER.png" alt="Slider">
  <span class="caption">Slider with tick marks</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_SLIDER_NoTicks.png" alt="Slider without ticks">
  <span class="caption">Slider without ticks</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_SLIDER_Disabled.png" alt="Disabled">
  <span class="caption">Disabled slider</span>
</div>

<div class="imgcaption">
  <img src="images/CustomSlider.png" alt="Custom drawn slider">
  <span class="caption">Custom drawn sliders with their buddy edits</span>
</div>

<p>The slider shares most of its properties with the progress bar:</p>
<ul>
  <li><tt>SIT_MinValue</tt>, <tt>SIT_MaxValue</tt>: work exactly like
  with the scrollbar: it is the range of values that will be reported.
  Default values are 0 and 100.</li>

  <li><tt>SIT_PageSize</tt>: the amount the slider's thumb will move
  when clicking inside the slider's channel. But unlike the scrollbar,
  this will not modify the size of the thumb, nor reduce the range of
  values being reported.</li>

  <li><tt>SIT_HorizScroll</tt>: by default slider are created with an
  horizontal slide. If you want it vertical, set this property to
  <tt class="o">False</tt>.</li>

  <li><tt>SIT_SliderPos</tt>: the position of the thumb (it is actually
  an alias of <tt>SIT_ScrollPos</tt>). Note that setting explicitely
  this property using <tt>SIT_SetValues()</tt> <strong>won't</strong>
  trigger your <tt>SITE_OnScroll</tt> callbacks.</li>
</ul>

<p>A few more are available:</p>
<ul>
  <li><tt>SIT_TickStyle</tt>: allows you to configure where tick marks will
  be set, among:
  <ul>
    <li><tt>SITV_TicksNone</tt>: only at beginning and ending position.</li>
    <li><tt>SITV_TicksTop</tt> or <tt>SITV_TicksBottom</tt>: whole length with
    thumb pointing in the given direction.</li>
    <li><tt>SITV_TicksTop|SITV_TicksBottom</tt>: top and bottom at the same
    time.</li>
  </ul></li>

  <li><tt>SIT_TickFreq</tt>: Display a tick every given unit. Unit is relative
  to the range you gave using minimum and maximum value, ie: giving 1 for
  TickFreq in a range of [0, 100], will draw 101 tick marks.</li>
</ul>

<p>Slider can be associated with a buddy control. It is a control that will
display the current slider value. Any changes on the slider will get
reflected on the buddy control (more precisely the <tt>SIT_Title</tt> property
will be set to the current value). If the buddy is an edit box, it will
also work the other way around: the edit will update the slider whenever its
value is changed. If you use an edit, it is advised to use a
<tt>SITV_Integer</tt> as for the <tt>SIT_EditType</tt> property.</p>

<p>Sliders like scrollbars report any change in its value through the
<tt>SITE_OnScroll</tt> event. And like scrollbars, <tt>call_data</tt>
can be casted to an integer to get the current thumb position.</p>

<p>Sliders also report to <tt>SITE_OnPaint</tt> event, to allow you
to customize part of the control. This event will be fired whenever the
slider has to be redrawn: this includes when it is being resized,
when the thumb is moving or when part of the area has been invalidated.
No caching/double-buffering will be done for you. To know which part
to redraw, use the function <tt>GFX_GetStage()</tt>, it returns
one of the following values:</p>
<ul>
  <li><tt>1</tt> : tick marks must be redrawn.</li>
  <li><tt>2</tt> : thumb must be redrawn.</li>
  <li><tt>3</tt> : channel awaiting refresh.</li>
</ul>

<p>If you <tt class="k">return</tt> <tt class="o">0</tt> in your callback,
the given part will be redrawn using the default theme. If you return
anything else, it will supposed you have handled the repainting operation.
To get the area to refresh for a specific stage, you must use the function
<tt>SIT_GetRefresh()</tt>. Do not draw outside this rectangle, especially
for the thumb, although you can refresh a smaller area, including an
irregular shape.</p>

<h3 id="SIT_PROGRESS">SIT_PROGRESS</h3>

<p>Progress are a way to let the user know about the advancement of a lengthy
operation:</p>

<div class="imgcaption">
  <img src="images/SIT_PROGRESS.png" alt="Plain progress bar">
  <span class="caption">Progress bar</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_PROGRESS_Caption.png" alt="Progress with caption">
  <span class="caption">With caption</span>
</div>

<p>Properties associated with progress bars are not that different from sliders
or scroll bars:</p>

<ul>
  <li><tt>SIT_MinValue</tt>, <tt>SIT_MaxValue</tt> (<tt class="t">int</tt>):
  the range of values you want to set the progress bar. Default values are 0 and
  100.</li>

  <li><tt>SIT_HorizScroll</tt> (<tt class="t">Bool</tt>):
  by default progress bar are created horizontal. If you want a vertical
  scroll bar, set this property to <tt class="o">False</tt>.</li>

  <li><tt>SIT_ProgressPos</tt> (<tt class="t">int</tt>):
  will set the progress indicator at the specified position. Like with
  slider it is an alias for <tt>SIT_ScrollPos</tt>, so it does not really
  matter if you accidently confuse them.</li>

  <li><tt>SIT_Title</tt> (<tt class="t">STRPTR</tt>): you can draw a caption
  over the progress bar.
  This title will be used as a format string for one of the <tt>printf</tt>
  family of functions. One argument will be given after that format string:
  the integer representing the current progress value, it up to you to
  format this number however you like, including not display it at all. It
  is advised to keep this property relatively short, like for example:
  <tt class="o">"<span class="s">%d%%</span>"</tt> (remember that to include
  a percent sign in a <tt>printf</tt> format string, you have to double it).
  Note that, the text has to be inside the progress bar. If you want it
  outside, you'll have to create a label and keep it in sync with the
  progress whenever you modify the latter.
  </li>
</ul>

<p>Progress bars report no specific events.</p>

<h3 id="SIT_DATETIME">SIT_DATETIME</h3>

<p>This control allows the user to select a date, a time or both:</p>

<div class="imgcaption">
  <img src="images/SIT_DATETIME.png" alt="Date selection">
  <span class="caption">Date selection</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_DATETIME_Popup.png" alt="Calendar popup">
  <span class="caption">Calendar popup</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_DATETIME_TimeOnly.png" alt="Time selection">
  <span class="caption">Time selection</span>
</div>

<p>The format of the date/time is controlled through the property <tt>SIT_DateFormat</tt>,
which can be assigned to the following values:</p>

<ul>
  <li><tt>SITV_DateShort</tt>: <tt>shortDate</tt> member of <tt>LocaleInfo</tt>
  structure.</li>
  <li><tt>SITV_DateLong</tt>: <tt>longDate</tt> member of <tt>LocaleInfo</tt>.</li>
  <li><tt>SITV_TimeOnly</tt>: <tt>timeStr</tt>.</li>
</ul>

<p>If you want more control, you can provide your own format string through the
property <tt>SIT_CustomTimeFmt</tt>. You can have an extensive description on
<a href="http://msdn.microsoft.com/en-us/library/bb761726.aspx#dtp_format_chars">MSDN</a>
web site.</p>

<p>Current date displayed by this control can be set/get with the property
<tt>SIT_CurrentDate</tt>. It expects a pointer to a <tt><span class="t">struct</span> tm</tt> as
argument, which is declared in the <tt>time.h</tt>. You can easily get a
pointer to such a structure using standard function from the libc, like
<a href="http://www.manpagez.com/man/3/localtime/"><tt>localtime()</tt></a> or
<a href="http://www.manpagez.com/man/3/localtime/"><tt>gmtime()</tt></a>.
If you want to retrieve the current date/time, you'll have to provide a valid
pointer to a buffer large enough to hold a <tt><span class="t">struct</span> tm</tt>.</p>

<p>DateTime controls report to only one event: <tt>SITE_OnChange</tt> (you can also
use <tt>SITE_OnChanged</tt>, although it will be seen as the same for this control).
The event will be fired whenever the user change the date/time within the control.
<tt>call_data</tt> parameter will be a pointer to a <tt><span class="t">struct</span>
tm</tt>. Return code is ignored.</p>

<h3 id="SIT_SPLITTER">SIT_SPLITTER</h3>

<p>A splitter allows you to divide an area in two parts (vertical or horizontal)
and let the user redistribute the amount to one or the other part:</p>

<div class="imgcaption">
  <img src="images/SIT_SPLITTER.png" alt="Horizontal splitter">
  <span class="caption">Horizontal splitter</span>
</div>

<div class="imgcaption" style="padding-left: 15px">
  <img src="images/SIT_SPLITTER_NoLive.png" alt="Moving splitter">
  <span class="caption">Moving splitter</span>
</div>

<div class="imgcaption" style="padding-left: 15px">
  <img src="images/SIT_SPLITTER_Holes.png" alt="Round holes style">
  <span class="caption">Using round holes style</span>
</div>

<p>The way splitters are intended to work is to move every controls that are
attached to one of its side. When a splitter is moved it will set its top/left
position (depending whether it is horizontal or vertical) as if you manually
set it yourself with <tt>SIT_X</tt>/<tt>SIT_Y</tt> properties. The layout
manager will then rearrange all widgets to take into account the new value.</p>

<p>Knowing this, you should see a pitfall coming here: if the splitter has
an attachment set relative to another control, the chain will not be broken
when moved, but it won't give you something you expected. Consider the following
layout:</p>

<div class="imgcaption" style="padding-right: 30px">
  <img src="images/SIT_SPLITTER_Attach.png" alt="Splitter attachment">
  <span class="caption">Splitter attachment</span>
</div>

<div class="imgcaption">
  <img src="images/SIT_SPLITTER_Resized.png" alt="Splitter resized">
  <span class="caption">Splitter resized</span>
</div>

<p>Those screenshots show the bounding rectangle of each control in blue.
The space between controls has also been enlarged to show you what's going
on.</p>

<p>The interesting part is on the left of the splitter. When it is moved,
the left attachment will be modified to reflect the position the user set it
to. If there was any relative attachment, it will be swapped with the relative
control, resulting in what you see in second screenshot: since the separator is
now trapper between two attachments, only this control will get resized when
the splitter is moved. To avoid this problem, either be sure there is only
one control on the left/top side, or set attachments so that they all are
initially relative to the splitter:</p>

<div class="imgcaption">
  <img src="images/SIT_SPLITTER_AttachAlt.png" alt="Splitter attachment">
  <span class="caption">Attachment tweaked</span>
</div>

<p>Also even if not displayed in this screenshot, the leftmost control has a
<tt>Form</tt> attachment on its left side, otherwise, the whole block will get
moved.</p>

<p>A few properties are available for this control:</p>

<dl>
  <dt><tt>SIT_HandleStyle</tt> (<tt class="t">int</tt>)</dt>
  <dd>Allow you to display a small handle to give user a hint that there is
  something to interact with. An enumeration value that can take the following
  value: <tt>SITV_RoundHoles</tt>, <tt>SITV_VerticalBar</tt> (does also apply
  for horizontal splitter) or <tt>SITV_FlatStyle</tt> (no indicator at all).</dd>

  <dt><tt>SIT_HorizSplit</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Whether or not the splitter will be horizontal or vertical.</dd>

  <dt><tt>SIT_LiveResize</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Default to <tt class="o">False</tt>. Indicate if the layout will be
  adjusted each time the splitter is moved (<tt class="o">True</tt>) or
  if it will display a hollow bar while moving (like in second screenshot
  above).
  </dd>
</dl>

<p>Splitters are implemented internally as <a href="#SIT_CANVAS">canvas</a>, so they
fire the same set of events. You might be interested in capturing a few of them.
For example, capturing <tt>SITE_OnPaint</tt> with a handle style set to
<tt>SITV_FlatStyle</tt> will allow you to draw your own handle.</p>

<h3 id="SIT_TAB">SIT_TAB</h3>

<p>Tab controls become handy when your interface grow to the point where it is hard
to fit everything in one dialog window and where you don't want to use separate
sub-dialog to present the options to the user:</p>

<div class="imgcaption" style="margin-right: 15px">
  <img src="images/SIT_TAB.png" alt="Single line tab">
  <span class="caption">Standard tab</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_TAB_MultiLine.png" alt="Tab spread over several lines">
  <span class="caption">Wrapped tabs</span>
</div>

<p>Tabs can be presented in 3 styles to the user, that can be chosen through the
<tt>SIT_TabStyle</tt> property:</p>
<ol>
  <li><b>Single line</b> (<tt>SITV_TabSingleLine</tt>): This is the default value.
  Tab will be spread over a single line. If there is not enough space to display
  one or more tabs unclipped, a group of arrows will appear to the right of the
  tabs, so that user can scroll through all tabs.</li>
  <li><b>Multiple line</b> (<tt>SITV_TabMultiLine</tt>): this style can be useful
  when there is a lot of tabs, while you still want to display all of them. Using
  a single line will often produce weird looking dialog, since the default behaviour
  of the layout manager will make the tab control large enough to display all tabs
  unclipped. Moreover dealing with scroll arrows is not always very user-friendly.
  The caveat of this kind style is that geometry management can somewhat be tricky,
  causing reflowing similar to multi-line labels.</li>
  <li><b>Invisible</b> (<tt>SITV_TabInvisible</tt>): this style is useful if you
  want to provide your own way to display tabs. A typical use case would be using
  a listbox on the left side, while having pages of your tab on the right side.
  Clicking on an item in the listbox will then display the desired page of the
  tab, by manually setting the <tt>SIT_CurTab</tt> property for example.</li>
</ol>

<div class="bgtip"><p class="tip">Caveat: Tab control on windows XP with theme enabled
is somewhat broken: if you are using the single line style and if overflow arrows ever
has to be displayed, push buttons will be clipped like this:
</p></div>


<p>Placing control within a specific tab, can be done using two methods:</p>
<ol>
  <li><b>Automatic</b>: you can use the macro <tt>SITV_TabNum(id,nb)</tt> to
  set the property <tt>SIT_TabOrder</tt>. Where <tt>id</tt> is the number of
  the tab you want the control to appear (and be hidden anywhere else). A small
  inconsistency to the usual 0-based indexing, is that the first tab is
  numbered 1. 0 is actually a special value, that will be described below.
  By setting this property, the layout manager will then be able to
  automatically set the <tt>SIT_Visible</tt> property according to the selected
  tab.</li>

  <li><b>Manual</b>: visibility of controls within tab can be manually managed
  by giving 0 as the id parameter of the <tt>SITV_TabNum</tt> macro (which is
  the default value when creating controls as children of tabs). This special
  value means that the control will be visible on all tabs. If you want to
  hide it, you will have to catch the <tt>SITE_OnChanged</tt> event and
  reorganized your controls here. A typical use case for this method is when
  the controls within the tabs are always the same: you usually don't want
  to duplicate all controls for each tab, you just create them once and adjust
  their content as the selected tab change, like for example a text editor
  with a tab to show/select opened files.</li>
</ol>

<p>It is actually possible to mix both methods: remember that using
<tt>SITV_TabNum()</tt> macro is only a way to automatically set the <tt>SIT_Visible</tt>
property.</p>

<p>A few more properties are available to manage tabs:</p>
<dl>
  <dt><tt>SIT_TabStr</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>Specify the initial list of tabs. It is a tab (ASCII code 9) separated
  list of names. e.g: <tt class="o">"First&nbsp;tab<span class="s">\t</span>Second&nbsp;tab<span class="s">\t</span>Third&nbsp;tab"</tt>.
  </dd>

  <dt><tt>SIT_CurTab</tt> (<tt class="t">int</tt>)</dt>
  <dd>Get/set the current selected tab (0-based index). Note setting this property
  won't trigger any <tt>OnChanged</tt> event.</dd>

  <dt><tt>SIT_NbTab</tt> (<tt class="t">int</tt>)</dt>
  <dd>Read-only. Get the number of tabs currently defined in this control.</dd>
</dl>

<p>To alter the list of tabs, you can also use the specialized function
<tt>SIT_TabSplice()</tt>. It's prototype is defined like this:</p>
<pre><span class="t">void</span> SIT_TabSplice(SIT_Widget w, <span class="t">int</span> pos, <span class="t">int</span> del, ...)</pre>

<p>It works similarly to the javascript <tt>Array.splice()</tt> method: you
can delete some tabs, starting a given index, then add some other, by specifying
a NULL-terminated list of strings.</p>

<p>The event <tt>SITE_OnChanged</tt> is fired whenever the selected tab changed. The <tt>call_data</tt>
can be converted into an integer to get the tab that has been selected (0-based index).</p>

<p>You can also trap <tt>SITE_OnClick</tt> to do actions with tabs using other mouse
buttons (typically right mouse button to display a contextual menu over tabs). This event
works like canvas, but when it is fired, the property <tt>SIT_TabInsertAt</tt> (<tt class="t">int</tt>) will be set
to the 0-based tab number where the mouse is over, or <tt>-1</tt> if not over a tab.

<h3 id="SIT_TOOLBAR">SIT_TOOLBAR</h3>

<p>Toolbar are rows of buttons that are usually located at the edge of the window.
They usually have a semantic similar to menus: this library actually allows a
close interaction between the two.</p>

<div class="imgcaption" style="float: left; margin: 0 5px 5px 0">
  <img src="images/SIT_TOOLBAR_Vertical.png" alt="Vertical toolbar">
  <span class="caption">Vertical toolbar<br>(<tt>SITV_Vertical</tt>)</span>
</div>
<div class="imgcaption" style="float: left; margin-right: 5px">
  <img src="images/SIT_TOOLBAR_VerticalLabel.png" alt="Vertical toolbar with labels">
  <span class="caption">With labels</span>
</div>
<div class="imgcaption">
  <img src="images/SIT_TOOLBAR.png" alt="Toolbar">
  <span class="caption">Toolbar - icons only</span>
</div>
<div class="imgcaption" style="margin-top: 8px">
  <img src="images/SIT_TOOLBAR_ListLabel.png" alt="Toolbar with some label">
  <span class="caption">With some label (<tt>SITV_ToolBarList</tt>)</span>
</div>
<div class="imgcaption" style="margin-top: 8px">
  <img src="images/SIT_TOOLBAR_Label.png" alt="Status bar">
  <span class="caption">Icon + labels</span>
</div>

<p style="clear: left">Toolbar main purpose is to contain buttons that are usually
shortcuts to menu commands. Although they behave like pushbuttons, buttons within
toolbar are not created using the generic control creation interface
(<tt>SIT_CreateWidget()</tt>). Instead toolbar are initialized using a method
similar to menus: you provide a structure that describes all the buttons that
will compose your toolbar. This structure is declared like this:</p>

<pre><span class="t">typedef struct</span>
{
	<span class="t">int</span>    id;
	<span class="t">STRPTR</span> text;
	<span class="t">int</span>    flags;
	<span class="t">STRPTR</span> icon;
	<span class="t">STRPTR</span> tooltip;
	<span class="t">APTR</span>   child;

}	SIT_ToolButton;</pre>

<p>Each field can be initialized that way:</p>

<dl>
  <dt><tt>id</tt></dt>
  <dd>ID of your button. This is useful if you want to later modify it. The
  special value <tt>SITTB_Separator</tt> can be used to insert a separator (in
  that case all the remaining fields can be left uninitialized). An ID
  of 0 marks the end of the list.</dd>

  <dt><tt>text</tt></dt>
  <dd>The text to display next to or below the icon of the button. Unless the
  toolbar has been created with the style <tt>SITV_ToolBarList</tt>, if you
  specify the text for one button, all others will leave some room to set a
  caption. <tt>text</tt> can be assigned to the special value
  <tt>SITTB_MenuName</tt>: the library will look for a menu item with the same
  ID as the tool button and use its label as the caption for the button. If
  the menu label includes an elipsis, it will be automatically removed.</dd>

  <dt><tt>flags</tt></dt>
  <dd>Defined the appearance/behaviour of the button. It is a bitfield that can
  be set with the following flags:
  <ul>
    <li><tt>SITTB_Button</tt>: this is the default style given for completeness,
    since its value is <tt class="o">0</tt>. It makes the button behaves like
    a standard push button, no more, no less, the only difference is that it
    notifies its activation using a <tt>SITE_OnMenu</tt> event instead of
    OnActivate.</li>

    <li><tt>SITTB_DropDown</tt>: a push button that will include an arrow next
    to its icon. This kind of button is supposed to display a popup menu when
    it is clicked. You'll get notified through a <tt>SITE_OnCtxMenu</tt>
    event.</li>

    <li><tt>SITTB_BtnPopup</tt>: a mix between <tt>Button</tt> and
    <tt>DropDown</tt>. This button is split in two: a left part that behaves
    like a push-button and a right part that's supposed to display a popup
    menu. The first button in the screenshots above show what it looks like.
    Fires both <tt>SITE_OnMenu</tt> and <tt>SITE_OnCtxMenu</tt> event.</li>

    <li><tt>SITTB_Child</tt>: an arbitrary control, created by
    <tt>SIT_CreateWidget()</tt> or derivative. You'll have to initialize the
    <tt>child</tt> member of the structure to give a pointer to this control.
    See the discussion below to know more about embedding controls within
    toolbars.</li>

    <li><tt>SITTB_Checked</tt>: indicate for a toggle button, that it will be
    displayed as activated (recessed).</li>

    <li><tt>SITTB_Hidden</tt>: the control will not be visible by default. Can
    be changed through dedicated API.</li>

    <li><tt>SITTB_Disabled</tt>: the button icon and text will appear grayed
    and will not respond to user interactions. Can be modified on the fly.</li>

    <li><tt>SITTB_AutoTips</tt>: tool buttons can display a small caption in
    an overlay as a reminder of the purpose of the button. You can either
    provide this text through the field <tt>tooltip</tt>, or let this library
    quote the label from the menu that have the same ID than this button, and
    that has this flag specified.</li>

    <li><tt>SITTB_Toggle(id)</tt>: used to define a toggle button or a group
    of mutually-exclusive toggle buttons. If you want a toggle button, set
    <tt>id</tt> to 0. If you want to define a group, include the next button
    ID that will be part of group. You'll have to include a separator before
    and after the group, if you are going to have groups next to each other.</li>

    <li><tt>SITTB_GfxImage</tt>: the field <tt>icon</tt> (see below) is
    actually a graphics-allocated image instead of a path to an icon. A copy
    will be made, life cyce of the original is up to you.
  </ul>
  </dd>

  <dt><tt>icon</tt></dt>
  <dd>The path of an image files that will be used as icon for the button.
  Remember to provide a 32bpp bitmap if your image is not perfectly square.
  The library will generate a disabled image for you. It has two algorithms:
  <ol>
    <li><strong>Convert to grayscale</strong>: this is the default behaviour.
    It works well only with color images obviously. If your image is already
    almost gray in its normal state, you might be interested in the other
    method.</li>

    <li><strong>Flatten and shift</strong>: your image is converted into a
    solid gray plane. Then a white mask is drawn below to give an "etched" look.
    To use this method, prefix your path with <tt class="o">"alt:"</tt>, it
    usually gives better results with image that have few colors.</li>
  </ol>

  <p>This field can be assigned to special values to load predefined bitmap
  from the operating system. These values begin with <tt>SITB_</tt>, and their
  names are rather self-explanatory. The graphical style might be simplistic
  for some of them, but if you don't want to bother creating or retouching your
  own, it is still better than nothing. You can have a preview of them on the
  <a href="http://msdn.microsoft.com/en-us/library/bb760433%28v=VS.85%29.aspx">MSDN</a>
  web site.</p>

  <p>The buttons will be scaled according to the first image you provided. If
  you ever provide images of different sizes, they will not be resized to fit
  its content. They will either be cropped if bigger, or sit in the upper left
  corner if smaller.</p>
  </dd>

  <dt><tt>tooltip</tt></dt>
  <dd>An arbitrary string you want to display when the mouse is hovered still
  for a short amount of time over the button. If you provide a string, the
  library will search for a menu with the same ID than this button, and check
  whether this menu has a shortcut or not. If it has one, it will be
  automatically added at the end of the tooltip (in parenthesis). Obviously,
  you'll have to setup your menu bar before creating your toolbar.
  </dd>

  <dt><tt>child</tt></dt>
  <dd>A pointer to a child control to be embedded within the toolbar. The
  button has to be set with the flag <tt>SITTB_Child</tt> for this field to
  be meaningful. See discussion below for more details.
  </dd>
</dl>

<p>For example, the first horizontal toolbar given as example above, has been
initialized that way:</p>

<pre><span class="t">static</span> SIT_ToolButton buttons[] = {
	{<span class="o">101</span>, <span class="o">NULL</span>, SITTB_BtnPopup, SITB_FileNew, <span class="o">"Open an existing file"</span>},
	{<span class="o">102</span>, <span class="o">NULL</span>, SITTB_Button,   SITB_FileOpen},
	{<span class="o">103</span>, <span class="o">NULL</span>, SITTB_Button,   SITB_FileSave},
	{SITTB_Separator},
	{<span class="o">201</span>, <span class="o">NULL</span>, SITTB_BtnPopup, SITB_Undo},
	{<span class="o">202</span>, <span class="o">NULL</span>, SITTB_Button,   SITB_Redo},
	{SITTB_Separator},
	{<span class="o">203</span>, <span class="o">NULL</span>, SITTB_Button|SITTB_Disabled, SITB_Cut},
	{<span class="o">204</span>, <span class="o">NULL</span>, SITTB_Button|SITTB_Disabled, SITB_Copy},
	{<span class="o">205</span>, <span class="o">NULL</span>, SITTB_Button, SITB_Paste},
	{SITTB_Separator},
	{<span class="o">501</span>, <span class="o">NULL</span>, SITTB_Button, <span class="o">"bitmap/help-system-16px.png"</span>},
	{}
};</pre>

<p>Once you have defined your list of buttons, you are ready to create the
control. There are a few properties available to do so:</p>

<dl>
  <dt><tt>SIT_ButtonList</tt> (<tt>SIT_ToolButton *</tt>)</dt>
  <dd>This is the property that expect your table of buttons. It is intended
  for creation only. If you ever want to modify the list of buttons afterward,
  you'll have to hide unwanted buttons.</dd>

  <dt><tt>SIT_ToolbarStyle</tt> (<tt class="t">int</tt>)</dt>
  <dd>Will define the appearance of your toolbar. It is an enumeration combined
  with a few bitfield flags (enum means only one of them can be chosen, while
  flag can be combined):
  <ul>
    <li><tt>SITV_ToolBarFlat</tt> (enum): default style. The first horizontal
    toolbar in the screenshots above has been created with that style.</li>

    <li><tt>SITV_ToolBarList</tt> (enum): this style will place label to the left of
    the buttons. Without it, labels will be placed below. If you only want to
    provide some labels for your buttons, you should use this style.</li>

    <li><tt>SITV_ToolBarButtons</tt> (enum): only really meaningful with common
    controls library v5. If will display the toolbar as buttons, instead of
    buttons that appears when the mouse is over them. For XP and later,
    this style has no effects.</li>

    <li><tt>SITV_NoDivider</tt> (flag): by default, toolbars draw a 2 pixels tall
    separator line above the buttons. This might be useful if your toolbar
    is placed just below the menu bar, if not you might be interested to
    remove it.</li>

    <li><tt>SITV_Vertical</tt> (flag): will dispose the buttons of the toolbar
    vertically. This style has some limitations though: mixing it with
    <tt>SITV_ToolBarList</tt> will usually give weird results,
    <tt>SITTB_BtnPopup</tt> and <tt>SITTB_DropDown</tt> button types will
    widen awkwardly the toolbar, and it is currently not possible to have
    multiple columns.</li>

    <li><tt>SITV_SyncWithMenu</tt> (flag): whenever the flag <tt>SITTB_Checked</tt>
    or <tt>SITTB_Disabled</tt> is changed on a tool button, the same change will
    be performed on the corresponding menu with the same ID as the button.</li>
  </ul>
  </dd>

  <dt><tt>SIT_LargeIcons</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>If you ever plan to use system icons. The default ones are 16x16 pixels.
  If you want bigger models, you can set this property to <tt class="o">True</tt>.
  Icons will then be 24x24px. Remember to scale your custom icons accordingly.
  </dd>
</dl>

<h4>Geometry of toolbars</h4>

<p>Toolbar's geometry will be initialized with a left, top, and right attachment
set to <tt>FORM</tt>. If you ever want to place it somewhere else, remember to
override those 3 sides. For example, if you want to place it in the bottom
corner, to the right of another control, don't forget to override top
attachment, because it does not default to <tt>NONE</tt> anymore:</p>

<pre>SIT_CreateWidget(<span class="o">"toolbar"</span>, SIT_TOOLBAR, dialog,
	SIT_ButtonList,       buttons,
	SIT_Left,             SITV_AttachWidget, ctrl, <span class="o">0</span>,
	SIT_TopAttachment,    SITV_AttachNone,
	SIT_BottomAttachment, SITV_AttachForm,
	<span class="o">NULL</span>
);</pre>

<p>For vertical toolbar, the top, left and bottom attachment will be set to
<tt>FORM</tt>, so that the toolbar will be anchored in the left side of the
dialog.</p>

<h4>Modifying attributes of buttons</h4>

<p>Modifying individual buttons is done through a dedicated function:</p>

<pre><span class="t">Bool</span> SIT_SetToolButton(SIT_Widget toolbar, <span class="t">int</span> id, <span class="t">int</span> flags, <span class="t">APTR</span> img);</pre>

<p><tt>id</tt> is the identifier you provided in the <tt>id</tt> member of the
<tt>SIT_ToolButton</tt> structure. <tt>flags</tt> parameter enables you to set
the state of the button (hidden, checked or disabled), while <tt>img</tt> will
allow you to change the image of the button. <tt>flags</tt> can be or'ed with
the following flags:</p>

<ul>
  <li><tt>SITTB_Checked</tt>: activate a toggle button or select one button
  within a group. It won't trigger any <tt>OnMenu</tt> callback, altough
  mutual-exclusivity will be enforced for you.</li>

  <li><tt>SITTB_Hidden</tt>: the button will be hidden, shifting the remaining
  buttons to the right.</li>

  <li><tt>SITTB_Disabled</tt>: will gray the button.</li>

  <li><tt>SITTB_AltGray</tt>: when changing the image of the button, this flag
  will indicate to use the flatten and shift for the grayed state, instead of
  converting the image into grayscale.</li>
</ul>

<p><tt>img</tt> has to be an image already loaded by <tt><a href="#loadbmp">GFX_LoadImage()</a></tt>
or derivative. A copy will be made, you retain the ownership of the pointer you
provided. If you don't want to change the image, you can provide the
special value <tt>DontChangePtr</tt>. If you provide <tt class="o">NULL</tt>,
the image will be removed.</p>

<h4>Embedding controls</h4>

<p>This might present a chicken-egg problem: controls must be created as
children of toolbar, while the <tt>SIT_ToolButton</tt> structure must be
filled with the reference of those controls before being given to the
<tt>SIT_ButtonList</tt> property. If you ever plan to include custom
controls, you'll have to do this in 3 steps:</p>

<ol>
  <li>Create your toolbar, without setting the <tt>SIT_ButtonList</tt>
  property yet.</li>
  <li>Create your custom controls as children of the toolbar.</li>
  <li>Assign the reference of your controls to the <tt>child</tt> member of
  the button array, then set the corresponding property.</li>
</ol>

<p>This works better with the <a href="#chapter10"><tt>SIT_CreateWidgets()</tt></a>
function, since step 1 and 2 can be done at the same time. For step 3, a helper
function allows you to do this in one function call: <tt>SIT_AssignToolButtons()</tt>.
Its prototype is declared this way:</p>

<pre><span class="t">void</span> SIT_AssignToolButtons(SIT_Widget toolbar, SIT_ToolButton *, ...);</pre>

<p>The interesting parameters are in the vararg part of the function: you have
to provide a list of pairs of tool button ID and control reference, ended by 0.
This function will then set the <tt>child</tt> members of the <tt>SIT_ToolButton</tt>
array you provided as second parameter of this function, and finally set the
corresponding property to realize all the buttons.</p>

<p>When embedded within a toolbar, geometric constraints applied on controls will
be ignored. Controls will be laid out from left to right. Remember that you still
you can embed a <a href="#SIT_CANVAS">canvas</a>, then put children with whatever
geometric constraints in this control instead of the toolbar.</p>

<h4>Events</h4>

<p>Button activation are reported through an <tt>SITE_OnMenu</tt> event. You
can register this event on the toolbar itself, although as a shortcut, if
none is set, the library will check if there such a callback on the dialog
where the toolbar is. Here is another reason to use the same ID for your
tool buttons than the one you use for your menu bar: that way you only have
to provide one callback, directly setup on the dialog.</p>

<p>For dropdown buttons, notifications will be reported through an
<tt>SITE_OnCtxMenu</tt> event. <tt>call_data</tt> will be an array
of <strong>3</strong> <tt class="t">int</tt>. The first index will
be the button ID, the next two will be the upper-left coordinate of
where the popup should be (aligned with the bottom left corner of the
button). You can use these coordinates to display a popup menu
using the function <tt>SIT_PopupMenu()</tt>. If you return a positive
value from your callback, the message will be considered processed,
otherwise an <tt>SITE_OnMenu</tt> will follow.</p>

<h3 id="SIT_TOOLTIP">SIT_TOOLTIP</h3>

<p>Tooltips are usually small popup windows that attempt to provide contextual
help to the user:</p>

<div class="imgcaption">
  <img src="images/SIT_TOOLTIP.png" alt="Tooltip">
  <span class="caption">Default tooltip</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_BallonTips.png" alt="Ballon tips">
  <span class="caption">Ballon tooltip</span>
</div>

<div class="imgcaption">
  <img src="images/SITV_BallonTipsIcon.png" alt="Ballon tips">
  <span class="caption">Tooltip with icon, header and balloon style</span>
</div>

<p>Tooltips can be created using two different methods:</p>

<ul>
  <li><strong>Manually</strong>: using a standard <tt>SIT_CreateWidget()</tt> function
  call. That way, you will have access to all the tooltip styles/options, although you
  will have to do a separate function call, which can be cumbersome to deal with.</li>
  <li><strong>Automatically</strong>: using <tt>SIT_ToolTip</tt> property on the
  control you want to attach the tooltip. This property is actually available on the
  base <tt>SIT_Widget</tt> class, so that it can be used on every kind of control.
  It is a string that will be displayed as the body text of the tooltip. The drawback
  is that you won't be able to customized its appearance/behaviour (it will always
  use the default style as shown above).</li>
</ul>

<p>If you decide to create your tooltips manually, you will be able to customize their
through the property <tt>SIT_Styles</tt>. It is a bit field that can be combined with
the following values:</p>

<ul>
  <li><tt>SITV_TooltipSquare</tt>: this is the default style, given for completeness.</li>
  <li><tt>SITV_TooltipBalloon</tt>: tooltips created with this style will have a stem
  pointing to the middle of the control where the tooltip is attached.</li>
  <li><tt>SITV_TooltipSticky</tt>: tooltip usually disappears automatically after a
  certain while. This style will make it stay on screen as long as the user didn't
  click somewhere.</li>
  <li><tt>SITV_TooltipHasClose</tt>: include a close button (header and icon must be
  set though). XXX useless.</li>
</ul>

<h3 id="SIT_STATUSBAR">SIT_STATUSBAR</h3>

<p>Status bars are a way to provide to users additional information,
usually to display state of various part of the application, like
key qualifiers, selected objects, current application state, etc...</p>

<div class="imgcaption">
  <img src="images/SIT_STATUSBAR.png" alt="Status bar">
  <span class="caption">Status bar with resize handle</span>
</div>

<p>Status bar are divided into parts, and each part can display text. If you
want more than text, you can register an <tt>OnPaint</tt> callback and draw
whatever you want in a given part. Statusbar will always be placed at the bottom
of the window and be constrained in that area whenever the dialog is resized.</p>

<p>Statusbar can only be created as a direct children of a dialog. Any attempt
to create it elsewhere will fail. Also if you add a status bar to a dialog that
already has one, it will be replaced by the new control. As mentionned in the
<a href="#dialogSize">dialog</a> section, the status bar isn't considered a part
of the client area of the window.</p>

<p>Status bars have the following specific properties:</p>

<ul>
  <li><tt>SIT_Styles</tt> (<tt class="t">int</tt>):
  The only supported style is <tt>SIT_HasResize</tt>, which will include a
  sizing box on the far right of the status bar. Remember to leave a room of
  20 pixels on the right when drawing and/or setting the part of your status
  bar.</li>

  <li><tt>SIT_LabelSize</tt> (<tt class="t">STRPTR</tt>):
  This property will let you configure the parts of your status bar. It is a
  tab-separated list of number and/or percentage. A number will set the width
  of the given part to the number of pixels specified. A percentage will set
  the width relative to the dialog's width (minus the sum of fixed width part
  of the status bar). For example
  <tt class="o">"100%<span class="s">\t</span>20<span class="s">\t</span>20"</tt>,
  will divide the status bar into 3 parts: the two rightmost will be 20 pixels
  wide, while the first one will occupy the remaining space.</li>
</ul>

<p>By default a part can only hold text, that can be set using the dedicated
function <tt>SIT_SetStatusText()</tt>:</p>
<pre><span class="t">void</span> SIT_SetStatusText(SIT_Widget w, <span class="t">STRPTR</span> text, <span class="t">int</span> part);</pre>

<p>Where <tt>w</tt> is either the handle of the status bar or, as a permitted
shortcut, the handle of the dialog. <tt>text</tt> is the text you want to be
displayed on the given zero-based index <tt>part</tt>. <tt>text</tt> can be
assigned to the special value <tt>SITV_OwnerDrawn</tt>, in order to receive
<tt>OnPaint</tt> notifications, so that can have fancier formatting options.</p>

<p>Status bars respond to 2 specific messages:</p>

<ul>
  <li><tt>SITE_OnClick</tt>: notify left and right click (button release) as
  well as left double-click. The part being clicked can be retrieved using the
  property <tt>SIT_StatusPart</tt> (<tt class="t">int</tt>).</li>

  <li><tt>SITE_OnPaint</tt>: if one or more parts of the status bar has been
  set owner drawn, you'll get one notification per part being set. Use
  <tt>GFX_GetRefresh()</tt> to get the rectangle of the area to refresh, while
  <tt>GFX_GetStage()</tt> will give the index of the part.
  </li>
</ul>

<h3>SIT_FILESELECT</h3>

<p>This dialog allows you to select a file to load and/or save:</p>

<div class="imgcaption">
  <img src="images/SIT_FILESELECT.png" alt="File chooser">
  <span class="caption">File chooser</span>
</div>

<p>The way this control is supposed to be used differs slightly from the
previous types we have seen so far. Actually when managing the dialog, it
will enter into a modal event loop, and the return code of the
<tt>SIT_ManageWidget()</tt> function will indicate whether or not the user
has confirmed or cancelled its selection. If confirmed, you can check some
properties to know what the selection was.</p>

<p>A few properties are available to customize this dialog:</p>

<dl>
  <dt><tt>SIT_Filters</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>Let you configure the list of available filters in the drop down list at
  the bottom of the dialog. It is a string specifying one filter per line
  (<tt>\n</tt> delimited). A filter is composed of a arbitrary name followed by
  tab (ASCII code 9) and then a semi-colon separated list of DOS wildcard. For
  example:
  <pre><span class="o">"C/C++ files<span class="s">\t</span>*.c;*.h;*.cpp;*.hpp<span class="s">\n</span>"
"Any<span class="s">\t</span>*"</span></pre></dd>

  <dt><tt>SIT_SelFilter</tt> (<tt class="t">int</tt>)</dt>
  <dd>Zero-based index within filter list that will be initially selected.</dd>

  <dt><tt>SIT_InitPath</tt> (<tt class="t">STRPTR</tt>)</dt>
  <dd>Initial path whose content will be displayed (UTF-8 encoded). <strong>The last
  part of this path</strong> will be use to pre-fill the file selection entry. If you
  want it to remain blank, add a final slash/anti-slash to your path.</dd>

  <dt><tt>SIT_DlgFlags</tt> (<tt class="t">int</tt>)</dt>
  <dd>Bit field that can be composed of the following flags:
  <ul>
    <li><tt>SITV_FileSave</tt>: the label of the dialog will reflect a save
    operation. Otherwise they will reflect a load operation.</li>

    <li><tt>SITV_FileMultiSelect</tt>: allow the user to select multiple files.</li>

    <li><tt>SITV_FileMustExist</tt>: ensure the file exists before returning
    from the event loop.</li>

    <li><tt>SITV_FileWarnOverwrite</tt>: warn the user that the selection will
    be overwritten.</li>
  </ul>
  </dd>
</dl>

<p>Once your control created, you usually manage it just like you would
with a normal dialog. Remember that the function will only return when
the dialog has been closed one way or another. If the user confirmed its
selection, you can check the properties <tt>SIT_SelPath</tt> and
<tt>SIT_NbSelect</tt> to know which paths have been selected and how many.
If more than one file has been selected, they will be appended one after
the other.</p>

<p>A typical usage would be:</p>

<pre><span class="t">int</span> handle_file(SIT_Widget w, <span class="t">APTR</span> cd, <span class="t">APTR</span> ud)
{
    <span class="t">static</span> SIT_Widget file;

    <span class="k">if</span> (file == <span class="o">NULL</span>)
        file = SIT_CreateWidget(<span class="o">"fileselect"</span>, SIT_FILESELECT, ud,
            SIT_Filters,   <span class="o">"C/C++ files<span class="s">\t</span>*.c;*.h;*.cpp;*.hpp<span class="s">\n</span>"
                           "Any<span class="s">\t</span>*"</span>,
            SIT_SelFilter, <span class="o">1</span>,
            SIT_DlgFlags,  SITV_FileMultiSelect | SITV_FileMustExist,
            <span class="o">NULL</span>
        );

    <span class="k">if</span> (SIT_ManageWidget(file))
    {
    	<span class="t">STRPTR</span> path;
	<span class="t">int</span>    nb;

        SIT_GetValues(file, SIT_SelPath, &amp;path, SIT_NbSelect, &amp;nb, <span class="o">NULL</span>);

        <span class="k">while</span> (nb &gt; <span class="o">0</span>)
        {
            fprintf(<span class="o">stderr</span>, <span class="o">"file selected = <span class="s">%s\n</span>"</span>, path);
            path = strchr(path, <span class="o">0</span>) + <span class="o">1</span>;
            nb --;
        }
    }
    <span class="k">return</span> <span class="o">1</span>;
}</pre>

<p>Take note that the control's object has been declared as static, and
is only created once and reused whenever the user trigger this callback.
This is to save a few settings that will be restored the next time the
dialog is displayed again, like:</p>
<ul>
  <li>Current directory selected.</li>
  <li>Filter selected.</li>
  <li>Position/dimension</li>
</ul>

<p>Memory for this control will actually be freed, when its parent dialog
gets closed.</p>

<h3 id="SIT_COLORSELECT">SIT_COLORSELECT</h3>

<p>This widget allows you to use stock color chooser from the system:</p>

<div class="imgcaption">
  <img src="images/SIT_COLORSELECT.png" alt="Color chooser">
  <span class="caption">Default color chooser (french locale)</span>
</div>

<p>Although its usability is rather poor (only HS&#215;V color space in preview,
no RGB/HSV sliders, no hexadecimal text field for copy/pasting HTML colors), it is
still a dialog that most users are familiar with. Like with <tt>SIT_FILESELECT</tt>,
the color selection dialog is intended to be used in a modal event loop: the
<tt>SIT_ManageWidget()</tt> function will only return when the user either select
a color or cancel the dialog, and return code will indicate whether (1) or not (0)
the user has made a selection. Once the execution get back to your callback, you'll
have to examine the <tt>SIT_SelColor</tt> (<tt class="t">ULONG</tt>) property to know
which color has been chosen.</p>

<p>A typical usage for this control would be:</p>

<pre><span class="t">int</span> handle_color(SIT_Widget w, <span class="t">APTR</span> cd, <span class="t">APTR</span> ud)
{
    <span class="t">static</span> SIT_Widget color;
    <span class="t">ULONG</span> colrgb;

    <span class="k">if</span> (color == <span class="o">NULL</span>)
        color = SIT_CreateWidget(<span class="o">"colorcc"</span>, SIT_COLORSELECT, ud, <span class="o">NULL</span>);

    <span class="k">if</span> (SIT_ManageWidget(color))
    {
        SIT_GetValues(color, SIT_SelColor, &amp;colrgb, <span class="o">NULL</span>);

        fprintf(<span class="o">stderr</span>, <span class="o">"color chosen = <span class="s">%06lx\n</span>"</span>, colrgb);
    }
    <span class="k">return</span> <span class="o">1</span>;
}</pre>

<p>Like with <tt>SIT_FILESELECT</tt>, the pointer of the color chooser is made
static, so that a few settings will be kept whenever it is managed, like current
color selected and the list of custom colors.</p>

<h3>SIT_FONTSELECT</h3>

<p>Font selection dialog allows the user to get a font specification suitable
for the <a href="#SIT_Font"><tt>SIT_Font</tt></a> property:</p>

<div class="imgcaption">
  <img src="images/SIT_FONTSELECT.png" alt="Font chooser">
  <span class="caption">Default font chooser (french locale)</span>
</div>

<p>Setting the initial font to be selected is done through the property
<tt>SIT_SelFont</tt> (<tt class="t">STRPTR</tt>). If it a format specification
that works exactly like <a href="#SIT_Font">SIT_Font</a>. If you do not set
this property before managing the dialog, the parent dialog's font will be
used instead. You can also set the <tt>SIT_FixedFont</tt> (<tt class="t">Bool</tt>)
property to request that only fixed font to be listed.</p>

<p>Once setup, its usage is pretty similar to the COLORSELECT and FILESELECT
dialogs. The <tt>SIT_ManageWidget()</tt> will initiate a modal event loop,
indicating by the return code whether (1) or not (0) the user selected
something. You can then examine the <tt>SIT_SelFont</tt> property to get the
font specification selected. For the sake of completeness, here is a classical
way to use this control:</p>

<pre><span class="t">int</span> handle_font(SIT_Widget w, <span class="t">APTR</span> cd, <span class="t">APTR</span> ud)
{
    <span class="t">static</span> SIT_Widget dialog;

    <span class="k">if</span> (dialog == <span class="o">NULL</span>)
        dialog = SIT_CreateWidget(<span class="o">"fontsel"</span>, SIT_FONTSELECT, ud, <span class="o">NULL</span>);

    <span class="k">if</span> (SIT_ManageWidget(dialog))
    {
    	<span class="t">STRPTR</span> font;
        SIT_GetValues(dialog, SIT_SelFont, &amp;font, <span class="o">NULL</span>);

        fprintf(<span class="o">stderr</span>, <span class="o">"font chosen = <span class="s">%s\n</span>"</span>, font);
    }
    <span class="k">return</span> <span class="o">1</span>;
}</pre>

<h3>SIT_DIRSELECT</h3>

<p>The directory selection control allows the user to navigate within local
drives and choose a specific folder:</p>

<div class="imgcaption">
  <img src="images/SIT_DIRSELECT.png" alt="Dir chooser">
  <span class="caption">Directory chooser</span>
</div>

<p>Like with most common dialogs from Microsoft, their look and feel tend not to
be very polished, but at least they are easily recognized by most users. In
this case, the wide margin at the top is not a bug, but just the lack of
caption. Well, that's what you got by using a poor layout manager.</p>

<p>As you might expect by now, its usage is very similar to the previous stock
dialogs. There is 2 properties you might be interested to set when creating
this kind of control:</p>

<ul>
  <li><tt>SIT_InitPath</tt>: the initial branch to display. It has to be a
  fully qualified path. If case the user confirms its selection, this
  property will be overwritten by the selected path.</li>

  <li><tt>SIT_Title</tt>: the text to display above the tree view.</li>
</ul>

<p>Here's a typical usage:</p>
<pre><span class="t">static</span> SIT_Widget dir;

<span class="k">if</span> (dir == <span class="o">NULL</span>)
    dir = SIT_CreateWidget(<span class="o">"dirsel"</span>, SIT_DIRSELECT, parent,
        SIT_Title,    <span class="o">"Select your destination path"</span>,
        SIT_InitPath, <span class="o">"C:/Projets/SIT"</span>,
        <span class="o">NULL</span>
    );

<span class="k">if</span> (SIT_ManageWidget(dir))
{
    <span class="t">STRPTR</span> path;
    SIT_GetValues(dir, SIT_InitPath, &amp;path, <span class="o">NULL</span>);
    fprintf(<span class="o">stderr</span>, <span class="o">"path selected = <span class="s">%s\n</span>"</span>, path);
}</pre>

<p>Note that although the <tt>SIT_InitPath</tt> has been initialized with
forward-slash path, if the user ever confirms its selection, this property
will use backslash instead.</p>

<h2 id="chapter9"><span class="num">IX.</span> Extra widgets</h2>

<p>This section will list a few widgets that are available as separate module to be
linked with your main program. They are implemented using no more than what has been
explained so far, they do not make use of private datatypes from SIT. Their source
code are also provided, if you feel you can improve them. They usually are rather
short (around 20Kb of source), so that you can even include the source file(s) to your
project.</p>

<h3>Property factory</h3>

<p>This library has a crude but small mecanism to add extra properties that can be
recognized by the functions <tt>SIT_SetValues()</tt> and <tt>SIT_GetValues()</tt>. The
problem when designing custom controls, is that it is usually quite common to have
lots of parameters for the user/programmer to fiddle with. You can still write your
own functions for handling this part, but you'll quickly find out that the only
easy way to deal with lots of properties is using a <em>vararg</em> interface, similar to
the <tt>SIT_SetValues()</tt> or <tt>SIT_GetValues()</tt> functions, because:</p>

<ul>
  <li>You do not have to remember the order in which to pass arguments.</li>
  <li>You can set/get any subset of all the available properties.</li>
  <li>There is provision to "bufferize" modification of properties (ie:
  setting several properties can still result in a single visual update,
  to avoid flickering problems).</li>
</ul>

<p>The drawback of this mecanism is that it does not work with the functions
<tt>SIT_CreateWidget()</tt>, <tt>SIT_CreateWidgets()</tt> and
<tt>SIT_SetAttributes()</tt>, although it is still better than nothing, or having
to write your own mecanism.</p>

<p>To implement custom attributes for your control, you'll first have to define
custom tags, that will be recognize as such by functions <tt>SIT_SetValues()</tt>
and <tt>SIT_GetValues()</tt>. User-defined tags starts with the value
<strong><tt>SIT_TagUser</tt></strong> or higher. Usually, you just have to
declare your attributes that way:</p>
<pre><span class="t">enum</span>
{
	MyAttribute1 = SIT_TagUser,
	MyAttribute2,
	MyAttribute3
	<span class="c">/* ... */</span>
};</pre>

<p>Then you have to register a callback for a <tt>SITE_OnSetOrGet</tt> notification.
It will be triggered whenever the user wants to get <strong>or</strong> set a custom
attribute (both actions are directed to the same callback). The call data is defined
this way:</p>
<pre><span class="t">struct</span> SIT_OnVal_t
{
	<span class="t">int</span>       stage;
	<span class="t">int</span>       tag;
	<span class="t">APTR</span>      ptr;
	<span class="t">va_list</span> * vararg;
};</pre>

<p>There is only two fields you might be interested in:</p>
<ul>
  <li><tt>stage</tt>: what action is requested by user. Either <tt>SITV_Set</tt>,
  <tt>SITV_Get</tt> or <tt>SITV_PostProcess</tt> (more on these later).</li>
  <li><tt>tag</tt>: the tag id.</li>
</ul>

<p><tt>ptr</tt> and <tt>vararg</tt> are managed through the use of macros. Let's first
see what the callback is expected to do according to current stage:</p>

<dl>
  <dt><tt>SITV_Get</tt></dt>
  <dd>User wants to get value of an attribute. You will have to use the macro
  <tt>SIT_SET(cd, val, type);</tt> (meaning you have to set the user variable).
  Where <tt>cd</tt> is the second argument (<tt>call_data</tt>) of your callback,
  <tt>val</tt> is the value you want to return to the user (and not a pointer to it).
  <tt>type</tt> is the type of the value.

  <p>If resources must be allocated for the value, it is strongly recommended to not let the user
  handle the deallocation of it. Since it is your control that allocates the memory, it is best if
  it is also yours that frees it. This can be implemented by some sort of caching mecanism,
  with the added benefit of being able the return later the same value if asked again.</p>

  <p>Return code is not meaningful for this stage.</p>
  </dd>

  <dt><tt>SITV_Set</tt></dt>
  <dd>The user ask to retrieve the value of a given tag. You can use the macro
  <tt>SIT_GET(cd, type);</tt> to get the value given by the user (this will be
  the actual value, not a pointer to it). Be careful with strings, this will be
  the original buffer provided by the user, it is strongly adviced to make a copy.
  
  <p>Also, even if your property if read-only, you'll have to use the <tt>SIT_GET</tt> macro,
  because of the way vararg works in C.<p>

  <p>If return code is positive, it will mean that you want to be notified once
  all arguments to <tt>SIT_SetValues()</tt> have been processed. That way you
  can process modifications in one shot, reducing potential flickering problems.</p>
  </dd>

  <dt><tt>SITV_PostProcess</tt></dt>
  <dd>If you returned a positive integer during a <tt>SITV_Set</tt> stage, another
  one will be triggered. If you ever intend to do some post-processing, the easiest
  way to handle this is to modify your internal datatypes along with a bitfield
  that give some hints as to what part has been modified during the <tt>SITV_Set</tt>
  stage. Once in the post-process stage, analyze that bitfield and modify part of
  the interface that need refresh. Return value is ignored for this stage.
  </dd>
</dl>

<h3>ViewImage</h3>

<p>This widget provide an easy way to display an image. It has been carefully designed
to provide very good performance for even large image (around 10,000x10,000px). This
widget does not only allows user to view the image, but also to zoom quickly from just
a small thumbnail up to a 32x magnification, including a full keyboard interface. The
reduction function also include a high quality anti-aliassing, that will lose very
few details. The only drawback is that you will have to load the entire image into memory,
there is no support for tiled image format.</p>

<p>This widget can display K, RGB, RGBA pre-multiplied or plain RGBA images. For images
with alpha channel, the alpha part will be filled (on the fly, the original image will
not be modified) with a solid color, hard-coded in the source (currently: #88888).</p>

<p>This kind of widget can be tedious to implement, although it has a rather
simple logic (it does its work by a combination of exponential resize, bicubic interpolation
and lazy evaluation). Using this as a starting base, will spare you some hassle.</p>

<p>To include this control in your project, simply grab the whole source code and add it to
your list. Since the code is rather small (25Kb) and does not use fancy features (no
inline assembly code, no compiler extensions, plain ISO C99, no internal structure from
SIT required), there is no incentives for providing something more evolved.</p>

<p>The way it is supposed to be initialized is that YOU will first have to create a
canvas widget, set its properties as you wish (with or without borders, attachments
and so on...), then, you'll have to call the following function:</p>

<pre><span class="t">Bool</span> ViewImageInit(SIT_Widget c, Image i);</pre>

<p>Where <tt>c</tt> is the reference to the canvas control you just created, and
<tt>i</tt> is the image you want to display (See <a href="#graphics">Graphics</a>
to know how to load/create image). This parameter can also be <tt class="o">NULL</tt>
if you want to set the image later. The return code will indicate if the
initialization has been successful or not.</p>

<p>Once the canvas has been created and properly initialized with this function, you
can set some properties (using <tt>SIT_SetValues()</tt>) to slightly alter its
behavior:</p>

<div class="imgcaption">
  <img src="images/ViewImageSample.jpg" alt="ViewImage widget in action">
  <span class="caption">Sample ViewImage widget</span>
</div>

<dl>
  <dt><tt>VIT_Image</tt> (<tt>Image</tt>)</dt>
  <dd>Allow you to set or reset the image currently displayed. You can provide
  <tt class="o">NULL</tt> if you do not want to display anything for now.</dd>

  <dt><tt>VIT_Factor</tt> (<tt class="t">double</tt>)</dt>
  <dd>The zoom factor you want to display the image. <tt class="o">1.0</tt>
  displays the image at its native resolution. <tt class="o">0.5</tt> will
  display it at half its original size. Valid range start from 0 (not including),
  up to 32 (including).</dd>

  <dt><tt>VIT_OffsetX</tt> (<tt class="t">int</tt>), <tt>VIT_OffsetY</tt> (<tt class="t">int</tt>)</dt>
  <dd>If part of the image is hidden, you might want to offset it to show a
  different part of it. These coordinates will set the pixel it points to the
  source image, into the top left corner of canvas according to the current
  zoom level. Default: <tt class="o">0</tt>, <tt class="o">0</tt>
  </dd>

  <dt><tt>VIT_AllowZoom</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>Whether or not you want the user to be able to modify the position and/or
  zoom level through the mouse or keyboard. If set to false, this widget will
  provide no interaction. Default: <tt class="o">True</tt>.</dd>

  <dt><tt>VIT_MiniMap</tt> (<tt class="t">Bool</tt>)</dt>
  <dd>When displaying very large images, it is useful to have to quick way
  to jump from one part to another. Scrollbars are usually cumbersome for
  this kind of task. By experience, the most user-friendly way to handle
  this is displaying a small thumbnail in one of the corner and centering
  the view over wherever the user clicks in this thumbnail (for this control
  it will always be placed in the bottom right corner, as can be seen in the
  screenshot above). This thumbnail will also include vertical and horizontal
  lines to quickly see what part is currently displayed. Also if the image is
  almost entirely visible, this minimap will be automatically hidden to avoid
  useless clutter on the display.</dd>

  <dt><tt>VIT_Overlay</tt> (<tt>SIT_CallProc</tt>)</dt>
  <dd>This property will give you a chance to draw stuff over the image as
  an overlay. In the example above, the zoom level has been added in the top
  left corner. Do not register your own <tt>OnPaint</tt> handler, this control
  will use double-buffering for RGBA images, and can provide the back-buffer
  directly to your callback. Your callback is expected to have the signature
  and the behavior of a standard <tt>OnPaint</tt> handler. Nothing more is
  required. In the example above, the overlay callback has been defined that way:
  <pre><span class="t">static int</span> my_overlay(SIT_Widget w, APTR gc, APTR ud)
{
	<span class="t">TEXT</span> num[<span class="o">16</span>];
	<span class="t">double</span> fact;
	SIT_GetValues(w, VIT_Factor, &amp;fact, <span class="o">NULL</span>);
	sprintf(num, <span class="o">"%.5g"</span>, fact);
	GFX_SetDrMd(gc, GFX_TxtModeTransparent);
	GFX_SetTextColor(gc, <span class="o">0</span>);
	GFX_Text(gc, num, <span class="o">-1</span>, <span class="o">5</span>, <span class="o">6</span>);
	GFX_SetTextColor(gc, RGB(<span class="o">255</span>,<span class="o">255</span>,<span class="o">255</span>));
	GFX_Text(gc, num, <span class="o">-1</span>, <span class="o">5</span>, <span class="o">5</span>);
	<span class="k">return</span> <span class="o">1</span>;
}</pre>
  </dd>

  <dt><tt>VIT_AutoFit</tt> (<tt class="t">int</tt>)</dt>
  <dd>If set to 1, the image will be automatically sized so that it is entirely
  visible within the canvas, even when the size of the canvas later changes. This is
  the default behavior. This property will automatically be set to 0 whenever
  the user manually change the zoom factor.</dd>
</dl>

<p>If you ever intend to modify the image after it is displayed within this
control, calling <tt>SIT_Refresh()</tt> won't be enough, since according to the
zoom factor, a cache will be created (like the minimap). If you modify the original, the cache
must also be updated: this is the purpose of the following function:</p>

<pre><span class="t">void</span> ViewImageInvalidate(SIT_Widget, <span class="t">int</span> x, <span class="t">int</span> y, <span class="t">int</span> w, <span class="t">int</span> h);</pre>

<p>Which works exactly like <tt>SIT_Refresh()</tt> (ie: setting <tt>w</tt> and
<tt>h</tt> to <tt class="o">0</tt> will refresh the entire image).</p>

<h3>ColorChooser</h3>

<p>This little control will spare you the hassle that every programmer on windows
have probably attempted: rewrite the stock color chooser dialog, which has a somewhat
poor usability. This version has been shamelessly stolen from GIMP, because it is highly
functionnal and very compact. It can handle RGB, HSV color space and optionally alpha
channel. Here is a typical look and feel of this dialog:</p>

<div class="imgcaption">
  <img src="images/ColorChooser.png" alt="Custom color chooser">
  <span class="caption">Sample color chooser dialog</span>
</div>

<p>It looks a little bit intimidating at first, but is pretty easy once you know what's
going on: the left part shows you the 3 dimentionnal color space using a 2D cross
section (known as the XY color space), along the remaining dimention, a.k.a the Z
color space (i.e: 2D + 1D = 3D). This latter dimension, can be chosen among 6 channels,
using the radio buttons to the left of the sliders. If the Z-channel belongs to the
HSV color space, the XY will be the remaining two from this color space. Similarly, if
the Z-channel is among the RGB, the XY will use the remaining channels from the RGB
space. The color gradient displayed by the sliders are preview of the range of colors that
this particular slider will produce if you move its thumb.</p>

<p>You can move sliders, use the integer fields on the right or simply use a hex value
encoded as <tt>#RRGGBB</tt> or <tt>#RRGGBBAA</tt> in the dedicated edit field to select
a color. The button on the right of this edit field allows you to pick a color from
anywhere on the screen. To do this, click on the button (do not release the mouse button),
move the mouse pointer where you want to pickup the color and release the button.</p>

<p>The system tab will show a list of pre-defined operating system colors from various
components (like foreground/background text selection color, window border color, ...).</p>

<p>The bottom part shows the currently selected color along with the color it was just
when the dialog was opened. The current color can be added to a list of predefined
colors using the arrow button. The "Reset" button with set the current color with that
old value.</p>


<p>Programmatically, it is very easy to use. There is one public function:</p>

<pre>SIT_Widget CCInit(SIT_Widget parent, CCState *);</pre>

<p><tt>CCState</tt> is a buffer used to init and get the result (if any) from the dialog.
It has the following fields:</p>

<dl>
<dt><tt>hasalpha</tt></dt>
<dd>Set this field to <tt class="o">True</tt> if you want RGBA color instead of just RGB.</dd>

<dt><tt>curcol</tt></dt>
<dd>The initial value displayed and (if confirmed by user) the color selected. This is a
<tt class="t">struct</tt>, where type field allows you to specify RGB{A} or HSV colors. If
<tt>type</tt> is 0, a default color will be chosen (white), if set to 1, the RGB{A} values
will be used and if set to 2, HSV components will be used.</dd>

<dt><tt>preset</tt>, <tt>winrect</tt></dt>
<dd>The predefined set of colors and the window dimension. Will be updated in the user
confirms its selection. You might want to save this somewhere (at least presets, because
they are useless otherwise).</dd>

<dt><tt>retcode</tt></dt>
<dd>This field will be 1 if the user confirms its selection, 0 otherwise</dd>
</dl>

<p>The return value will be a <tt>SIT_DIALOG</tt> widget. When passed to the
<tt>SIT_ManageWidget(SIT_Widget);</tt> function, it will enter into a modal event
loop, returning from this function only when user confirms or cancels the dialog.
Once returned, the selection will be stored in the <tt>CCState</tt> buffer you
provided earllier. Memory will be freed by now, so there is no need for any destructor
function.</p>

<h2 id="chapter10"><span class="num">X.</span> Reducing code overhead</h2>

<p>As mentionned in the chapter V, creating an interface through a
series of <tt>SIT_CreateWidget()</tt> function calls can become very tedious,
not to mention a code layout that hardly give any hints as to where a given
part of the interface is being created. Consider the login/password dialog
presented <a href="#diagex2">here</a>, a way to implement that interface using
tags/values would be:</p>

<pre><span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])
{
	SIT_Widget app = SIT_CreateWidget(<span class="o">"track-it"</span>, SIT_APP, <span class="o">NULL</span>, <span class="o">NULL</span>);
	SIT_Widget tbl[<span class="o">4</span>];

	SIT_Widget dialog = SIT_CreateWidget(<span class="o">"loginscr"</span>, SIT_DIALOG, app,
		SIT_Title,   <span class="o">"Login"</span>,
		SIT_Margins, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>,
		<span class="o">NULL</span>
	);

	SIT_Widget ctrl = SIT_CreateWidget(<span class="o">"&amp;Login :"</span>, SIT_LABEL, dialog,
		SIT_AlignHoriz, SITV_AlignRight,
		<span class="o">NULL</span>
	);
	SIT_Widget edit = SIT_CreateWidget(<span class="o">"login"</span>, SIT_EDITBOX, dialog,
		SIT_Title, <span class="o">""</span>,
		SIT_Width, <span class="o">250</span>,
		SIT_Left,  SITV_AttachWidget, ctrl, <span class="o">5</span>,
		SIT_Right, SITV_AttachForm,   <span class="o">NULL</span>, <span class="o">0</span>,
		<span class="o">NULL</span>
	);
	SIT_SetValues(ctrl, SIT_Top, SITV_AttachMiddle, edit, <span class="o">0</span>, <span class="o">NULL</span>);

	ctrl = SIT_CreateWidget(<span class="o">"&amp;Password :"</span>, SIT_LABEL, dialog,
		SIT_AlignHoriz, SITV_AlignRight,
		SIT_MaxWidth,   ctrl,
		<span class="o">NULL</span>
	);
	edit = SIT_CreateWidget(<span class="o">"passwd"</span>, SIT_EDITBOX, dialog,
		SIT_EditType, SITV_Password,
		SIT_Title,    <span class="o">""</span>,
		SIT_Left,     SITV_AttachWidget, ctrl, <span class="o">5</span>,
		SIT_Right,    SITV_AttachForm,   <span class="o">NULL</span>, <span class="o">0</span>,
		SIT_Top,      SITV_AttachWidget, edit, <span class="o">5</span>,
		<span class="o">NULL</span>
	);
	SIT_SetValues(ctrl, SIT_Top, SITV_AttachMiddle, edit, <span class="o">0</span>, <span class="o">NULL</span>);

	SIT_Widget button = SIT_CreateWidget(<span class="o">"</span><span class="s">\xE2\x96\xBC</span><span class="o">"</span>, SIT_PUSHBUTTON, dialog,
		SIT_RightAttachment, SITV_AttachForm,
		SIT_TabOrder,        <span class="o">37</span>,
		SIT_Font,            <span class="o">"Arial"</span>,
		<span class="o">NULL</span>
	);

	ctrl = SIT_CreateWidget(<span class="o">"&amp;Server :"</span>, SIT_LABEL, dialog,
		SIT_AlignHoriz, SITV_AlignRight,
		SIT_MaxWidth,   ctrl,
		<span class="o">NULL</span>
	);
	edit = tbl[<span class="o">3</span>] = SIT_CreateWidget(<span class="o">"server"</span>, SIT_EDITBOX, dialog,
		SIT_EditType, SITV_Password,
		SIT_Title,    <span class="o">""</span>,
		SIT_Left,     SITV_AttachWidget, ctrl,   <span class="o">5</span>,
		SIT_Right,    SITV_AttachWidget, button, <span class="o">5</span>,
		SIT_Top,      SITV_AttachWidget, edit,   <span class="o">5</span>,
		<span class="o">NULL</span>
	);
	SIT_SetValues(ctrl,   SIT_Top, SITV_AttachMiddle, edit, <span class="o">0</span>, <span class="o">NULL</span>);
	SIT_SetValues(button, SIT_Top, SITV_AttachMiddle, edit, <span class="o">0</span>, <span class="o">NULL</span>);

	ctrl = tbl[<span class="o">0</span>] = SIT_CreateWidget(<span class="o">"sep"</span>, SIT_LABEL, dialog,
		SIT_FrameStyle, SITV_EtchedHoriz,
		SIT_Top,        SITV_AttachWidget, edit, <span class="o">5</span>,
		SIT_Left,       SITV_AttachForm,   <span class="o">NULL</span>, -<span class="o">100</span>,
		SIT_Right,      SITV_AttachForm,   <span class="o">NULL</span>, -<span class="o">100</span>,
		<span class="o">NULL</span>
	);

	tbl[<span class="o">1</span>] = SIT_CreateWidget(<span class="o">"srvlist"</span>, SIT_LISTBOX, dialog,
		SIT_Visible,      <span class="o">False</span>,
		SIT_Top,          SITV_AttachWidget, edit, <span class="o">5</span>,
		SIT_Left,         SITV_AttachForm,   <span class="o">NULL</span>, <span class="o">0</span>,
		SIT_Right,        SITV_AttachForm,   <span class="o">NULL</span>, <span class="o">0</span>,
		SIT_Bottom,       SITV_AttachWidget, ctrl, <span class="o">5</span>,
		SIT_ColumnNames,  <span class="o">"Name</span><span class="s">\t</span><span class="o">Address</span><span class="s">\t</span><span class="o">Machine"</span>,
		SIT_ColumnWidths, <span class="o">"2*<span class="s">\t</span>*<span class="s">\t</span>*"</span>,
		SIT_Height,       <span class="o">100</span>,
		SIT_ListBoxFlags, SITV_FullRowSelect,
		<span class="o">NULL</span>
	);
	SIT_ListInsertItem(tbl[<span class="o">1</span>], -<span class="o">1</span>, <span class="o">"PPIT v3.5.2.5"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"S1"</span>, <span class="o">NULL</span>);
	SIT_ListInsertItem(tbl[<span class="o">1</span>], -<span class="o">1</span>, <span class="o">"PPIT v3.6.0.1"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"LAB1430"</span>, <span class="o">NULL</span>);
	SIT_ListInsertItem(tbl[<span class="o">1</span>], -<span class="o">1</span>, <span class="o">"PPIT v3.6.0.1"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"D5KV3JM1"</span>, <span class="o">NULL</span>);

	SIT_AddCallback(button, SITE_OnActivate, handle_button, tbl);

	button = tbl[<span class="o">2</span>] = SIT_CreateWidget(<span class="o">"Lo&amp;gin"</span>, SIT_PUSHBUTTON, dialog,
		SIT_ButtonType, SITV_DefaultButton,
		SIT_Margins,    <span class="o">0</span>, <span class="o">10</span>, <span class="o">0</span>, <span class="o">10</span>,
		SIT_Top,        SITV_AttachWidget, ctrl, <span class="o">5</span>,
		<span class="o">NULL</span>
	);

	button = SIT_CreateWidget(<span class="o">"&amp;Exit"</span>, SIT_PUSHBUTTON, dialog,
		SIT_ButtonType, SITV_CancelButton,
		SIT_Margins,    <span class="o">0</span>, <span class="o">10</span>, <span class="o">0</span>, <span class="o">10</span>,
		SIT_MaxWidth,   button,
		SIT_Left,       SITV_AttachNoOverlap, button, <span class="o">10</span>,
		SIT_Top,        SITV_AttachOpposite,  button, <span class="o">0</span>,
		SIT_Right,      SITV_AttachForm,   <span class="o">NULL</span>, <span class="o">0</span>,
		<span class="o">NULL</span>
	);

	SIT_ManageWidget(dialog);

	<span class="k">return</span> SIT_Main();
}</pre>

<p>Which is rather verbose and confusing, because all those statements
look very similar. Hopefully, this library has another interface for creating
widgets and setting attributes. It was originally planned as a way to get a
snapshot of the interface, that could be stored in a file, and then later be
used to restore the layout of the dialog. It turned out that it can also be
used to create the controls with less code overhead.</p>

<p>This API is not a complete replacement of the generic tag/value model. It is
especially targetted to those interfaces that consist mostly of static content,
with lots of controls and very few room for building them through loops. In
such case, using the plain <tt>SIT_CreateWidget()</tt> is very tedious. On the
other way, if you created your interface through control structures,
like <tt class="k">for</tt>, <tt class="k">while</tt> or <tt class="k">if</tt>,
this API is poorly suited. The good news is that both APIs can be perfectly
mixed together, since at its heart, this API is just a fancy wrapper around the
<tt>SIT_CreateWidget()</tt> and <tt>SIT_SetValues()</tt> functions.</p>

<h3>The serialized model</h3>

<p>To understand how this interface works, we need to go back to where we
introduced the tag/value model. So far, everytime we try to set an attribute
(a.k.a tag or property) we used an enumeration like <tt>SIT_Title</tt>,
<tt>SIT_Left</tt>, ... Actually every properties have also a string associated.
This string is case-insensitive and is simply the enumeration value, without the
<tt>SIT_</tt> prefix. Internally they are written using camel case, e.g.
<tt>SIT_LeftAttachment</tt> can be accessed through <tt class="o">"leftAttachment"</tt>.</p>

<p>Those strings can be used to form HTML-like tags with key/value statements
to create controls or set their values. If you want to create a control, the
tag name is actually the control type, whereas if you want to set attributes,
the tag name is actually the control's name for which attributes will be set.
The tag name is then followed by a list of key/value pairs, using the HTML
notation: <tt>key=value</tt>, where <tt>value</tt> can be enclosed by single
or double quotes if it contains spaces. To escape a value use the
<tt>&amp;#DD;</tt> or <tt>&amp;#xXX;</tt> notation, where <tt>DD</tt> is a
decimal number and <tt>XX</tt> an hexadecimal one, representing the unicode
code point of the character you want to escape (anti-slash will be interpreted
as a normal character and other HTML entities are not recognized).</p>

<p>There is one special key that does not have a corresponding enumeration
property: it is the name of the control (since it is given as the first argument
to <tt>SIT_CreateWidget()</tt>). As you would surely have guessed by yourself now,
the key to set this information is simply "<tt>name</tt>". This key is actually
a little bit more important when using this model than when using the tag/value
model, because in the latter, it is common to use the name of the control as a
shortcut for the <tt>SIT_Title</tt> property, as you'll get a reference to the
control you created. In the former, you won't get that reference, and if you
need it, you'll have to use <tt>SIT_GetById()</tt>.</p>

<p>For example, to create a label as a child of a given dialog, you can use
the following function call:</p>

<pre>SIT_CreateWidgets(dialog, <span class="o">"&lt;label name=hello title='hello, world'&gt;"</span>);</pre>

<p>For properties that require more than one argument, you'll have to specify
them using a comma-separated list. Missing arguments will be set to
<tt class="o">0</tt> or <tt class="o">NULL</tt>. For example:</p>

<pre>SIT_CreateWidgets(dialog,
    <span class="o">"&lt;label name=sep left=FORM right=FORM top=WIDGET,server,5 frameStyle=1&gt;"</span>);</pre>

<p>That means the comma is a special character, and if you ever want to include
it in a string, you will have to single or double quote it. When combined with
multiple arguments, remember to leave the comma outside the quotes, like this:

<pre>SIT_CreateWidgets(dialog,
    <span class="o">"&lt;label name=sep left=FORM right=FORM top=WIDGET,'hello, world',5 frameStyle=1&gt;"</span>);</pre>

<p>The following table lists the available tag names that can be created:</p>

<div class="table">
<table>
<thead>
  <tr><td>Tag name</td><td>SIT Type</td>
      <td>Tag name</td><td>SIT Type</td></tr>
</thead>
<tbody>
  <tr><td><tt>label</tt></td><td><a href="#SIT_LABEL"><tt>SIT_LABEL</tt></a></td>
      <td><tt>button</tt></td><td><a href="#SIT_PUSHBUTTON"><tt>SIT_PUSHBUTTON</tt></a></td></tr>
  <tr><td><tt>frame</tt></td><td><a href="#SIT_FRAME"><tt>SIT_FRAME</tt></a></td>
      <td><tt>listbox</tt></td><td><a href="#SIT_LISTBOX"><tt>SIT_LISTBOX</tt></a></td></tr>
  <tr><td><tt>canvas</tt></td><td><a href="#SIT_CANVAS"><tt>SIT_CANVAS</tt></a></td>
      <td><tt>scrollbar</tt></td><td><a href="#SIT_SCROLLBAR"><tt>SIT_SCROLLBAR</tt></a></td></tr>
  <tr><td><tt>slider</tt></td><td><a href="#SIT_SLIDER"><tt>SIT_SLIDER</tt></a></td>
      <td><tt>progress</tt></td><td><a href="#SIT_PROGRESS"><tt>SIT_PROGRESS</tt></a></td></tr>
  <tr><td><tt>combobox</tt></td><td><a href="#SIT_COMBOBOX"><tt>SIT_COMBOBOX</tt></a></td>
      <td><tt>datetime</tt></td><td><a href="#SIT_DATETIME"><tt>SIT_DATETIME</tt></a></td></tr>
  <tr><td><tt>tab</tt></td><td><a href="#SIT_TAB"><tt>SIT_TAB</tt></a></td>
      <td><tt>splitter</tt></td><td><a href="#SIT_SPLITTER"><tt>SIT_SPLITTER</tt></a></td></tr>
  <tr><td><tt>statusbar</tt></td><td><a href="#SIT_STATUSBAR"><tt>SIT_STATUSBAR</tt></a></td>
      <td><tt>toolbar</tt></td><td><a href="#SIT_TOOLBAR"><tt>SIT_TOOLBAR</tt></a></td></tr>
  <tr><td><tt>editbox</tt></td><td><a href="#SIT_EDITBOX"><tt>SIT_EDITBOX</tt></a></td>
      <td><tt>tooltip</tt></td><td><a href="#SIT_TOOLTIP"><tt>SIT_TOOLTIP</tt></a></td></tr>
</tbody>
</table>
</div>

<p>Which is basically like the enumeration without the <tt>SIT_</tt> prefix
(except for <tt>SIT_PUSHBUTTON</tt>, a small inconsistency spotted a little
bit late and not really worth rectifying). Also tag names are not case
sensitive.</p>

<h3>Using enumeration values</h3>

<p>Some properties expect an enumeration value, which, in the end, is only an
integer. But, except for attachment specification, this interface has no means to
translate a string into a numeric value, unless the string is an integer by
itself (like we do for the frameStyle property in the example above: 1 is the
value for <tt>SITV_EtchedHoriz</tt>). Since remembering what's the integer
value for all those attributes is way too tedious, this interface allows you to
specify directly the enumeration value, by ending prematurably the string just
after the equal sign, and then give the arguments as you would have with the
<tt>SIT_CreateWidget()</tt> function. The example above can also be written
that way:</p>

<pre>SIT_CreateWidgets(dialog,
    <span class="o">"&lt;label name=sep left=FORM right=FORM top="</span>, SITV_AttachWidget, server, <span class="o">5</span>,
    <span class="o">"frameStyle=&quot;</span>, SITV_EtchedHoriz , <span class="o">"&gt;"</span>);</pre>

<p>The only caveat is when an attribute requires more than one value. If you
specify one argument using a <em>vararg</em>, all of them must be specified
the same way, and just like with the <tt>SIT_CreateWidget()</tt> function,
be careful to not miss one.</p>

<p>A few predefined constants are available for the <tt>SIT_LeftAttachment</tt>,
<tt>SIT_TopAttachment</tt>, <tt>SIT_RightAttachment</tt> and <tt>SIT_BottomAttachment</tt>
properties (also available for the one that indirectly reference them, like
<tt>SIT_Left</tt>, ...). You can use the following string in place of the
corresponding integer:</p>

<div class="table">
<table>
<thead>
  <tr><td>Tag name</td><td>SIT Type</td>
      <td>Tag name</td><td>SIT Type</td></tr>
</thead>
<tbody>
  <tr><td><tt>NONE</tt></td><td><tt>SITV_AttachNone</tt></td>
      <td><tt>FORM</tt></td><td><tt>SITV_AttachForm</tt></td></tr>
  <tr><td><tt>OPPOSITE</tt></td><td><tt>SITV_AttachOpposite</tt></td>
      <td><tt>MIDDLE</tt></td><td><tt>SITV_AttachMiddle</tt></td></tr>
  <tr><td><tt>NOOVERLAP</tt></td><td><tt>SITV_AttachNoOverlap</tt></td>
      <td><tt>POSITION</tt></td><td><tt>SITV_AttachPosition</tt></td></tr>
  <tr><td><tt>WIDGET</tt></td><td><tt>SITV_AttachWidget</tt></td>
      <td></td><td></td></tr>
</tbody>
</table>
</div>

<p>Also, for the <tt>SIT_*Object</tt> group, if you use a string specification,
the argument with be interpreted as a widget name, that will be searched with
<tt>SIT_GetById()</tt>. You have to be sure the widget exists though: this
is the primary reason why widgets are first created, and then you set
their layout attributes. This is usually not a bad thing, since that way
you have to separate the content from the cosmetics.</p>

<p>Once all arguments have been given, you can continue your string to specify
more attributes, or create more controls.</p>

<h3>Nested tags</h3>

<p>Some controls are designed to be used as container for other controls, and
as such will require an explicit closing tag, otherwise all subsequent tag
declarations will be created as children of this control. For instance, there
is 4 controls that do this implicit behaviour: <tt>canvas</tt>, <tt>tab</tt>,
<tt>frame</tt> and <tt>toolbar</tt>. If you want to nest controls in a
container that does not nest by default, you'll have to use <tt>SIT_GetById()</tt>
first, then perform a separate <tt>SIT_CreateWidgets()</tt> call.</p>

<p>Also as a little shortcut, if your tag declaration doesn't contain any
children, you can end it using the XML notation: <tt>/&gt;</tt>, sparing you
the hassle to write the ending tag. Actually it doesn't hurt if you specify
it even for non-nesting tags.</p>

<h3>Example</h3>

<p>Knowing all this, you are now able to rewrite the example given at the
beginning to use this new interface:</p>

<pre>
<span class="t">static int</span> expand(SIT_Widget w, <span class="t">APTR</span> cd, <span class="t">APTR</span> ud)
{
   SIT_Widget list = SIT_GetById(ud, <span class="o">"srvlist"</span>);
   Bool visible;

   SIT_GetValues(list, SIT_Visible, &amp;visible, <span class="o">NULL</span>);
   SIT_SetValues(list, SIT_Visible, !visible, <span class="o">NULL</span>);

   SIT_SetAttributes(ud, visible ?
      <span class="o">"&lt;sep1 bottom=NONE top=WIDGET,server,5&gt;&lt;pblogin bottom=NONE top=WIDGET,sep1,5&gt;&lt;expand title=<span class="s">&amp;#x25BC;</span>&gt;"</span> :
      <span class="o">"&lt;sep1 bottom=WIDGET,pblogin,5 top=NONE&gt;&lt;pblogin bottom=FORM top=NONE&gt;&lt;expand title=<span class="s">&amp;#x25B2;</span>&gt;"</span>);

   <span class="k">return</span> <span class="o">1</span>;
}

<span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])
{
   SIT_Widget app = SIT_CreateWidget(<span class="o">"track-it"</span>, SIT_APP, <span class="o">NULL</span>, <span class="o">NULL</span>);
   SIT_Widget ctrl = <span class="o">NULL</span>;
   SIT_Widget dialog = SIT_CreateWidget(<span class="o">"loginscr"</span>, SIT_DIALOG, app,
      SIT_Title,   <span class="o">"Login"</span>,
      SIT_Margins, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>,
      <span class="o">NULL</span>
   );

   SIT_CreateWidgets(dialog,
      <span class="o">"&lt;editbox name=login width=250 minWidth=100 buddyLabel="</span>, <span class="i">_(</span><span class="o">"&amp;Login :"</span><span class="i">)</span>, &amp;ctrl, <span class="o">"&gt;"</span>
      <span class="o">"&lt;editbox name=passwd editType="</span>, SITV_Password, <span class="o">"buddyLabel="</span>,
         <span class="i">_(</span><span class="o">"&amp;Password :"</span><span class="i">)</span>, &amp;ctrl, <span class="o">"&gt;"</span>
      <span class="o">"&lt;editbox name=server buddyLabel="</span>, <span class="i">_(</span><span class="o">"&amp;Server :"</span><span class="i">)</span>, &amp;ctrl, <span class="o">"&gt;"</span>
      <span class="o">"&lt;button name=expand title=<span class="s">&amp;#x25BC;</span> font=Arial&gt;"</span>
      <span class="o">"&lt;listbox name=srvlist columnNames='Name</span><span class="s">\t</span><span class="o">Address</span><span class="s">\t</span><span class="o">Machine' visible=0"</span>
      <span class="o">" columnWidths='2*</span><span class="s">\t</span><span class="o">*</span><span class="s">\t</span><span class="o">*' listBoxFlags="</span>, SITV_FullRowSelect, <span class="o">"height=80&gt;"</span>
      <span class="o">"&lt;label name=sep1 frameStyle=&quot;</span>, SITV_EtchedHoriz, <span class="o">"&gt;"</span>
      <span class="o">"&lt;button name=pblogin title="</span>, <span class="i">_(</span><span class="o">"Lo&amp;gin"</span><span class="i">)</span>, <span class="o">"buttonType="</span>, SITV_DefaultButton, <span class="o">"&gt;"</span>
      <span class="o">"&lt;button name=cancel title="</span>, <span class="i">_(</span><span class="o">"&amp;Exit"</span><span class="i">)</span>, <span class="o">"buttonType="</span>, SITV_CancelButton, <span class="o">"&gt;"</span>
   );

   SIT_Widget list = SIT_GetById(dialog, <span class="o">"srvlist"</span>);
   SIT_ListInsertItem(list, -<span class="o">1</span>, <span class="o">NULL</span>, <span class="o">NULL</span>, <span class="o">"PPIT v3.5.2.5"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"S1"</span>, <span class="o">NULL</span>);
   SIT_ListInsertItem(list, -<span class="o">1</span>, <span class="o">NULL</span>, <span class="o">NULL</span>, <span class="o">"PPIT v3.6.0.1"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"LAB1430"</span>, <span class="o">NULL</span>);
   SIT_ListInsertItem(list, -<span class="o">1</span>, <span class="o">NULL</span>, <span class="o">NULL</span>, <span class="o">"PPIT v3.6.0.1"</span>, <span class="o">"127.0.0.1"</span>, <span class="o">"D5KV3JM1"</span>, <span class="o">NULL</span>);
   SIT_AddCallback(SIT_GetById(dialog, <span class="o">"expand"</span>), SITE_OnActivate, expand, dialog);

   SIT_SetAttributes(dialog,
      <span class="o">"&lt;login right=FORM&gt;"</span>
      <span class="o">"&lt;passwd top=WIDGET,login,5 right=FORM&gt;"</span>
      <span class="o">"&lt;server top=WIDGET,passwd,5 right=WIDGET,expand,5&gt;"</span>
      <span class="o">"&lt;expand right=FORM top=MIDDLE,server&gt;"</span>
      <span class="o">"&lt;srvlist left=FORM right=FORM top=WIDGET,server,5 bottom=WIDGET,sep1,5&gt;"</span>
      <span class="o">"&lt;sep1 top=WIDGET,server,5 left=FORM,,-10 right=FORM,,-10&gt;"</span>
      <span class="o">"&lt;pblogin margins=0,10,0,10 top=WIDGET,sep1,5&gt;"</span>
      <span class="o">"&lt;cancel maxwidth=pblogin top=OPPOSITE,pblogin,0 right=FORM left=NOOVERLAP,pblogin,10&gt;"</span>
   );
   SIT_ManageWidget(dialog);

   <span class="k">return</span> SIT_Main();
}</pre>

<h2><span class="num">XI.</span> Menus</h2>

<h2 id="graphics"><span class="num">XII.</span> Graphics</h2>

<p>Graphics is a small, but crude, module integrated into SIT to do basic
graphics operations, like drawing lines, rectangles, bitmaps and text. Its
capabilities are somewhat limited to keep the overhead low, although it is
possible to use external libraries, like <a href="http://msdn.microsoft.com/en-us/library/ms533798(VS.85).aspx">GDI+</a> or <a href="http://cairographics.org/">Cairo</a>.
The main motivation for not providing a full featured 2D API is that it is a
daunting task, not really worth doing when there already is well designed APIs.
The one used by SIT is based on plain GDI, which means that quality is rather
poor (e.g: no anti-aliassed vector drawing).</p>

<h3>Graphics context</h3>

<p>Before being able to use any graphic primitives, you need to get a handle
on a graphic context. This context describes, or even contains in the case of
off-screen bitmaps, the surface you will be drawing on. You already have seen
graphic context when talking about <a href="#SITE_OnPaint"><tt>OnPaint</tt></a>
event, this part will explain more precisely how to obtain them. It is an opaque
pointer, whose typedef'ed name is <tt>GC</tt> (the complete one is <tt><span class="t">struct</span>
GC_t *</tt>) that can also be accessed through a generic pointer like <tt class="t">void *</tt>
or <tt class="t">APTR</tt>, although for the sake of static type checking it
is advised to use as often as possible the typedef name.</p>

<p>To obtain a reference to a graphic context outside the event cycle, there is
usually two ways:</p>

<ol>
  <li><b>On-screen bitmap</b>: you can get a handle of a existing control,
  (usually a canvas) using the function <tt>GFX_GetGC()</tt> where you draw
  stuff directly on the screen.</li>
  <li><b>Off-screen bitmap</b>: you allocate a buffer that is not visible
  on the screen, using <tt>GFX_AllocOffScreen()</tt>. You will then be able to
  copy that context into a screen context later, using <tt>GFX_CopyGC()</tt>.
  This is the basis of double-buffered rendering.</li>
</ol>

<p>Whatever method you'll use, the return value of those functions will be
a reference to a graphic context, where you can draw stuff on.</p>

<h3>Drawing primitives</h3>

<p>This section will be kept short because, there is a lot of functions, and
most of them are pretty straightforward:</p>

<dl>
  <dt><tt><span class="t">void</span> GFX_SetTextColor(GC, <span class="t">int</span> color);<br>
  <span class="t">void</span> GFX_SetBgColor(GC, <span class="t">int</span> color);</tt></dt>
  <dd>Change the foreground/background color. Must be an RGB color (not RGBA). You can
  use the macro <tt>RGB(r, g, b)</tt> for the <tt>color</tt> parameter.</dd>

  <dt><tt><span class="t">int</span> GFX_SetSysColor(GC, <span class="t">int</span> color, <span class="t">Bool</span> bg)</tt></dt>
  <dd>Set either the foreground (<tt>bg == False</tt>) or background color using a system
  defined color (See <tt>GFX_Color*</tt> defines). The return value will give you the RGB
  equivalent. It is allowed to set the GC parameter to NULL to only get the RGB value.</dd>

  <dt><tt><span class="t">void</span> GFX_SetPen(GC, <span class="t">int</span> width, <span class="t">ULONG</span> color);</tt></dt>
  <dd>Set the pen uses to draw lines. A width of 0 means the smallest possible width
  permitted by the device. -1 means no pen (useful for filling polygons without drawing any
  borders). You can use <tt>SYSCOL</tt> macro for <tt>color</tt> parameter.</dd>

  <dt><tt><span class="t">void</span> GFX_Move(GC, <span class="t">int</span> x, <span class="t">int</span> y);<br>
  <span class="t">void</span> GFX_Draw(GC, <span class="t">int</span> x, <span class="t">int</span> y);</tt></dt>
  <dd>Move current drawing point, and draw a line using current pen.</dd>

  <dt><tt><span class="t">void</span> GFX_Scroll(SIT_Widget, <span class="t">int</span> dx, <span class="t">int</span> dy, <span class="t">int</span> x, <span class="t">int</span> y, <span class="t">int</span> w, <span class="t">int</span> h);</tt></dt>
  <dd>One of the few function that need a window parameter and not a graphic context.
  This function will shift the content of the rectangle specified by <tt>x</tt>, <tt>y</tt>,
  <tt>w</tt> and <tt>h</tt>. <tt>dx</tt> and <tt>dy</tt> will respectively shift content 
  to the right/bottom. If they are negative, they shift content to the left/top instead.
  The region "uncovered" by the shift will receive an <tt>OnPaint</tt> notification.
  </dd>

  <dt><tt><span class="t">int</span> GFX_TextLength(GC, <span class="t">STRPTR</span> str, <span class="t">int</span> nb);<br>
  <span class="t">int</span> GFX_TextLengthW(GC, <span class="t">const wchar_t</span> * str, <span class="t">int</span> len);</tt></dt>
  <dd>Measure text in pixels, using respectively UTF-8 and UTF-16 encoding. <tt>len</tt> is the number
  of bytes (and not characters) of the message to measure. If <tt>len</tt> is negative,
  <tt>str</tt> is supposed to be NULL-terminated.</dd>

  <dt><tt><span class="t">int</span> GFX_TextFit(GC, <span class="t">STRPTR</span> str, <span class="t">int</span> max, <span class="t">int</span> maxwidth, <span class="t">int</span> * width);</tt></dt>
  <dd>This function will determine how many characters can fit within <tt>maxwidth</tt> pixels.
  <tt>str</tt> is supposed to be at most <tt>max</tt> bytes long, or if negative, it suppose
  to be NULL-terminated. The return value is the number of characters that can fit the space.
  Optionnaly, it can also return the length of those character, sparing you the need to call
  <tt>GFX_TextLength()</tt>.</dd>

  <dt><tt><span class="t">int</span> GFX_Text(GC, STRPTR str, <span class="t">int</span> nb, <span class="t">int</span> x, <span class="t">int</span> y);<br>
  <span class="t">int</span> GFX_TextW(GC, <span class="t">const wchar_t</span> * text, <span class="t">int</span> len, <span class="t">int</span> x, <span class="t">int</span> y);</tt></dt>
  <dd>Draw specified text using respectively UTF-8 and UTF-16 encoding. The <tt>x</tt> and <tt>y</tt>
  parameter specify the starting position of the upper right corner of the text. Return the new
  horizontal position (XXX italic font).</dd>

  <dt><tt><span class="t">void</span> GFX_DrawRect(GC, <span class="t">int</span> x, <span class="t">int</span> y, <span class="t">int</span> x2, <span class="t">int</span> y2);<br>
  <span class="t">void</span> GFX_FillRect(GC, <span class="t">int</span> x, <span class="t">int</span> y, <span class="t">int</span> x2, <span class="t">int</span> y2);<br>
  <span class="t">void</span> GFX_FillRectS(GC, Rect *);<br>
  <span class="t">void</span> GFX_XorRect(GC, <span class="t">int</span> x, <span class="t">int</span> y, <span class="t">int</span> w, <span class="t">int</span> h);</tt></dt>
  <dd>Draw a rectangle or fill a rectangle. When filling, no borders will be drawn.</dd>

  <dt><tt><span class="t">void</span> GFX_Polygon(GC, <span class="t">int</span> * points, <span class="t">int</span> nb, <span class="t">int</span> mode);<br>
  <span class="t">void</span> GFX_FillPolygon(GC, <span class="t">int</span> * points, <span class="t">int</span> nb, <span class="t">int</span> mode);</tt></dt>
  <dd>Draw or fill a polygon using current pen and background color. '<tt>mode</tt>' can either
  be <tt>GFX_CoordModePrevious</tt> or <tt>GFX_CoordModeAbs</tt> (default). <tt>ModePrevious</tt>
  Will assume than every points, except the first, is relative to the previous one. I.e: an array
  initialized with <tt>{x, y, <span class="o">5</span>, <span class="o">0</span>, <span class="o">0</span>,
  <span class="o">5</span>, -<span class="o">5</span>, <span class="o">0</span>}</tt> will draw a
  square with sides 5 pixels long. '<tt>mode</tt>' can also be or'ed with the following flags:
  <ul>
    <li><tt>GFX_BezierCurve</tt>: will draw bezier curve instead of straight lines. <tt>nb</tt> must
    be a multiple of 3.</li>
    <li><tt>GFX_ClosePolygon</tt>: implicit when filling, when drawing it will automatically
    connects the last point with the first (In case of bezier lines, it will draw a straight line,
    not a curve).</li>
  </ul>
  The polygon will be drawn without anti-aliasing, using integer grid as for placement, if you want a better quality function check out <a href="http://en.literateprograms.org/Polygon_Rasterization_%28C%29">this page</a>.
  </dd>

  <dt><tt><span class="t">void</span> GFX_FillGradient(GC gc, Rect * r, <span class="t">int</span> orient, <span class="t">ULONG</span> col1, <span class="t">ULONG</span> col2, ...);</tt></dt>
  <dd>Fill the given rectangle with a linear gradient of evenly spaced colors (RGB only, no RGBA). '<tt>orient</tt>' is limited
  to 0, 90, 180 or 270. The last item in the vararg list must be <tt>GFX_ColorStop</tt> or <tt>(<span class="t">ULONG</span>)-<span class="o">1</span></tt>. If you want a function with more capabilities, check out <a href="http://en.literateprograms.org/Linear_gradient_%28C%29">this page</a>.</dd>

  <dt><tt><span class="t">APTR</span> GFX_GetSysImage(<span class="t">STRPTR</span> path, <span class="t">STRPTR</span> * desc, <span class="t">STRPTR</span> * type);</tt></dt>
  <dd>This function will get the system icon associated with the specified file.
  It will be a 32bpp image that can be copied on any device context using <tt>GFX_SetPixels()</tt>.
  This icon will not include any custom overlay, like for example shared folders or desktop shortcuts.
  <tt>desc</tt> is an optional string that will receive the name displayed by the file explorer.
  <tt>type</tt> is the file of type that can usually be presented to the user. Memory for both
  <tt>desc</tt> and <tt>type</tt> will be associated with the image returned, so that they will
  be freed when you destroy the image using <tt>GFX_FreeImage()</tt>.
  
  <p>By default large (32x32px) icons will be loaded. You can prefix <tt>path</tt> by <tt class="o">"small:"</tt>
  to load the small (16x16px) icon.</p>

  <p>Some examples:</p>
  <dl>
    <dt><tt>image = GFX_GetSysImage(<span class="o">"C:<span class="s">\\</span>"</span>, <span class="o">NULL</span>, <span class="o">NULL</span>);</tt></dt>
    <dd>Will get the icon associated to the C drive.</dd>

    <dt><tt>image = GFX_GetSysImage(<span class="o">"C:<span class="s">\\</span>MyApp.exe"</span>, <span class="o">NULL</span>, <span class="o">NULL</span>);</tt></dt>
    <dd>Will get the icon of the file <tt>MyApp.exe</tt>.</dd>

    <dt><tt>image = GFX_GetSysImage(<span class="o">".exe"</span>, <span class="o">NULL</span>, <span class="o">NULL</span>);</tt></dt>
    <dd>Will get the default icon for applications.</dd>

    <dt><tt>image = GFX_GetSysImage(<span class="o">"small:.txt"</span>, <span class="o">NULL</span>, <span class="o">NULL</span>);</tt></dt>
    <dd>Will get the default small icon for text document.</dd>

    <dt><tt>image = GFX_GetSysImage(<span class="o">"open:small:.folder"</span>, <span class="o">NULL</span>, <span class="o">NULL</span>);</tt></dt>
    <dd>Will get the default small icon for opened folder.</dd>
  </dl>
  </dd>

  <dt><tt><span class="t">APTR</span> GFX_GetFont(<span class="t">STRPTR</span> fmt);<br>
  <span class="t">APTR</span> GFX_LoadFont(<span class="t">STRPTR</span> family, <span class="t">int</span> h, <span class="t">int</span> weight, <span class="t">int</span> style);<br>
  <span class="t">void</span> GFX_CloseFont(<span class="t">APTR</span> hfont);<br>
  <span class="t">void</span> GFX_SetFont(GC, <span class="t">APTR</span> font);<br>
  <span class="t">void</span> GFX_GetFontInfo(GC, TextFont * out);</tt></dt>
  <dd>Manage fonts within context. '<tt>fmt</tt>' accept the same syntax than
  <a href="#SIT_Font"><tt>SIT_Font</tt></a> property. '<tt>weight</tt>' is the
  boldness of the font: 300 is regular, 700 is bold. Max is 1000, min 100.
  '<tt>style</tt>' is a bitfield that can be combined with following defines:
  <tt>GFX_FSItalic</tt>, <tt>GFX_FSUnderline</tt> and <tt>GFX_FSStrike</tt>. Any
  font opened by <tt>GFX_GetFont()</tt> or <tt>GFX_LoadFont</tt> must be closed
  by <tt>GFX_CloseFont()</tt>. XXX not good</dd>

  <dt><tt><span class="t">void</span> GFX_SetDrMd(GC, <span class="t">int</span> mode);</tt></dt>
  <dd>Determine how text will be printed on screen, among:
  <ul>
    <li><tt>GFX_TxtModeTransparent</tt>: background of text will be transparent, leaving whatever
    there was before the drawing. Foreground will use the default text color.</li>
    <li><tt>GFX_TxtModeOpaque</tt>: background will use the current background color.</li>
  </dd>
</dl>

<p>This list is not exhaustive, check out the file <tt>graphics.h</tt> for the complete
list of functions. For those who know a little bit of GDI programming, might wonder if
it required to "clean-up" the graphic context before returning to the library, as it is
required by GDI: of course this library will take care of that for you.</p>

<h3 id="loadbmp">Handling bitmaps</h3>

<p>This library can handle 3 types of bitmap:</p>
<ul>
  <li>8bpp grayscale</li>
  <li>24bpp RGB</li>
  <li>32bpp RGBA</li>
</ul>

<p>Those bitmaps can be read from 3 different file formats: BMP, PNG and JPEG,
which can be stored in 3 different ways: inline as a stringified blob, as a
windows resource or as external files. The basic function to load an image is
this one:</p>

<pre>Image GFX_LoadImage(STRPTR img);</pre>

<p><tt>img</tt> usually is a path to a standard file. If you want to load
an image as a resource, you'll have to start your "path" by "<tt>res://</tt>",
followed by the resource id, possibly followed by a slash and a resource type
(see chapter <a href="#chapter15">Resources</a> to understand those terms).
If the resource type is missing, the bitmap will suppose to be a BMP. While
if it is included, its format will be checked in the first bytes of the
resource to either load a PNG or JPEG picture. To load a stringified blob,
you must start your path by "<tt>data://</tt>", then followed by exactly
4 bytes encoding the size of the blob (not including this header) using a
<strong>big endian</strong> integer. There is a program that can generate
this kind of string for you, check out <a href="chapter15">chapter XV</a>.
All these methods will convert the bitmap to the native format used by the
system: BGR or BGRA with 32bit padded scan line and pre-multiplied by alpha
channel. If you want the raw value of the bitmap, prefix the path by
<tt>raw://</tt> (works for all except resources).</p>

<p><tt>Image</tt> is a public structure: you are allowed to <strong>read</strong>
the fields, but avoid changing any values (except the bitmap data of course).
It is declared this way:</p>

<pre><span class="t">typedef struct</span>
{
    <span class="t">int</span>   width;     <span class="c">/* width in pixels */</span>
    <span class="t">int</span>   height;    <span class="c">/* height */</span>
    <span class="t">int</span>   format;    <span class="c">/* GFX_Format* */</span>
    <span class="t">int</span>   stride;
    <span class="t">int</span>   encoder;   <span class="c">/* GFX_Encoder* */</span>
    <span class="t">int</span>   bpp;       <span class="c">/* 8, 24 or 32 */</span>
    DATA8 bitmap;    <span class="c">/* Image's data */</span>
    <span class="t">APTR</span>  hbitmap;   <span class="c">/* Internal */</span>
} * Image;
</pre>

<p>Most fields are self-explanatory. Some may require additional information:
<tt>stride</tt> is the length in bytes of each scanline. <tt>Win32</tt> bitmap
requires scanline to be 32bit aligned. You have to use this field to jump from
one scanline to the next if you want to read image's data. <tt>hbitmap</tt> is
the low-level device handle, it is managed by this library do not modify it.</p>

<p>Here are some examples:</p>

<dl>
  <dt><tt>GFX_LoadImage(<span class="o">"C:<span class="s">\\</span>MyImage.png"</span>);</tt></dt>
  <dd>Will load the file "<tt>MyImage.png</tt>" that is located at the root of
  the C drive.</dd>

  <dt><tt><small>GFX_LoadImage(<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">"data://<span class="s">\0\0\x02</span>u<span class="s">\x89</span>PNG<span class="s">\x0d\n\x1a\n\0\0\0\x0d</span>IHDR<span class="s">\0\0\0\x10\0\0\0\x10\x08\x06\0\0\0</span>"<br>
&nbsp;&nbsp;&nbsp;&nbsp;"<span class="s">\x1f</span>&oacute;&yuml;a<span class="s">\0\0\0\x01</span>sRGB<span class="s">\0</span>&reg;&Icirc;<span class="s">\x1</span>c&eacute;<span class="s">\0\0\0\x06</span>""bKGD<span class="s">\0</span>&yuml;<span class="s">\0</span>&yuml;<span class="s">\0</span>&yuml;&nbsp;&#xbd;&#xa7;<span class="s">\x93\0\0\0\t</span>pHYs<span class="s">\0\0\x0b</span>"<br>
&nbsp;&nbsp;&nbsp;&nbsp;"<span class="s">\x13\0\0\x0b\x13\x01\0\x9a\x9c\x18\0\0\0\x07</span>tIME<span class="s">\x07</span>&Uacute;<span class="s">\x06\x10\0\x1f\"</span>&#xb8;<span class="s">\x12</span>x&#xac;<span class="s">\0\0\0\x19</span>"<br></span>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="c">/* More lines following, but not shown here .... */<br></span>
);</small></tt></dt>
  <dd>Will load the bitmap directly from the string provided. The 4 bytes
  following the <tt>data://</tt> header, indicates that the blob is 629 bytes long, and is
  encoded as a PNG image.</dd>

  <dt><tt>GFX_LoadImage(<span class="o">"res://1"</span>);</tt></dt>
  <dd>Will try to load the BMP image that has the ID 1. Usually this is the ID of
  the application's icon, as displayed by file managers and such.</dd>

  <dt><tt>GFX_LoadImage(<span class="o">"res://1/256"</span>);</tt></dt>
  <dd>Will either load a PNG or JPEG image stored as a resource, usually declared
  this way in the RC file: <pre>1 256 "path/to/image.png"</pre></dd>
</dl>

<p>Each method has its advantages/drawbacks, some of them can by summarized here:</p>

<div class="table">
<table>
  <thead>
    <tr><td>Method</td><td>Advantages</td><td>Drawbacks</td></tr>
  </thead>
  <tbody>
    <tr>
      <td>External&nbsp;files</td>
      <td><ul><li>User can easily replace the bitmap with their own version.</li>
      <li>Straitforward to implement.</li>
      </ul></td>
      <td><ul><li>Has to be packaged in one way or another.</li>
      </ul></td>
    </tr><tr>
      <td>Resources</td>
      <td><ul><li>Included with the application, no need to worry losing some files.</li>
      <li>Loaded on demand, does not use memory on startup.</li>
      </ul></td>
      <td><ul><li>A bit tricky to load resource from a DLL. Better to avoid in static
      library.</li>
      <li>Need to deal with resource compiler file.</li>
      </ul></td>
    </tr><tr>
      <td>Inline&nbsp;blob</td>
      <td><ul><li>Can be embedded everywhere, using any format supported by this library.</li>
      <li>Straitforward to implement, small overhead.</li></ul></td>
      <td><ul><li>Loaded on startup, no mean to free the blob afterward.</li>
      </ul></td>
    </tr>
  </tbody>
</table>
</div>

<p>Consider all of this wisely when trying to choose which method you want
to handle bitmap within your application. Once you've successfully loaded
an image, you can then draw it on a graphic context, using the following
function:</p>

<pre><span class="t">void</span> GFX_SetPixels(Image src, <span class="t">int</span> xs, <span class="t">int</span> ys, <span class="t">int</span> ws, <span class="t">int</span> hs,
                   GC dst, <span class="t">int</span> xd, <span class="t">int</span> yd, <span clas="t">int</span> wd, <span class="t">int</span> hd);</pre>

<p>This function has a dual purpose: copy all or part of your bitmap, and
resizing this part it in the process if you want. Alpha channel will be
taken into account, that means this function can produce high-quality
anti-aliassed graphics.</p>

<h3>Using alternate rendering library</h3>

<p>GDI is a rather poor rendering library when dealing with vector graphics, and
even worse when it comes with bitmaps, although this library has done its best
to alleviate this issue. Still, you might be interested by some alternatives:</p>

<ul>
  <li><tt>GDI+</tt>: the successor of GDI, introduced in Windows XP, and thus
  pre-installed on almost every system. GDI+ can also be used on Windows 2000.
  Note that its native encoding is UTF-16. As of december 2010, development has
  ceased and library is in maintenance mode. Also, the only public API is written
  in C++, the C API is private.</li>

  <li><tt><a href="http://cairographics.org/">Cairo</a></tt>: an open-source 2d
  rendering library, that has a rendering approach similar to postscript and PDF.
  Used by most major open-source software (Firefox, GTK, SWT, ...),
  has a lots of rendering backend, like postscript, PDF, SVG and of course, video
  memory. The native encoding is UTF-8, just like SIT. Not installed by default,
  although still highly deployed.</li>
</ul>

<p>Another alternate API you might be interested in is Direct2D, a GPU-assisted rendering
abstraction library. Not described here, because its API is a bit tedious (may have
improved with latest (&gt;9) versions).</p>

<p>The key function to enable the bridge between SIT and one of the rendering library,
is the following function:</p>

<pre>APTR GFX_GetDevice(GC);</pre>

<p>It will return the low-level device used to do the rendering. For example to use
GDI+ in an <tt>OnPaint</tt> notification, you can use a code like this:</p>

<pre><span class="t">static int</span> OnPaint(SIT_Widget w, APTR gc, APTR ud)
{
	HDC        hdc = (HDC)GFX_GetDevice((GC)gc);
	Graphics   graphics(hdc);
	FontFamily fontFamily(<span class="o">L"Arial"</span>);
	Font       font(&amp;fontFamily, <span class="o">12</span>, FontStyleRegular, UnitPixel);
	PointF     point(<span class="o">10</span>, <span class="o">10</span>);
	SolidBrush brush(Color(<span class="o">0</span>,<span class="o">0</span>,<span class="o">0</span>));
	WCHAR      str[] = <span class="o">L"Hello world !"</span>;

	graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
	graphics.DrawString(str, <span class="o">-1</span>, &amp;font, point, &amp;brush);

	<span class="k">return</span> <span class="o">1</span>;
}</pre>

<p>Note the casts when using <tt>GFX_GetDevice()</tt>. This is mandatory because
this function has to be compiled using a C++ compiler. Remember that C and C++
can be reasonably mixed together: you do not have to write the whole application
in C++ in you intend to use GDI+.</p>

<p>For Cairo, it is relatively similar:</p>

<pre><span class="t">static int</span> OnPaint(SIT_Widget w, APTR gc, APTR ud)
{
	HDC               hdc = (HDC)GFX_GetDevice((GC)gc);
	cairo_surface_t * crs = cairo_win32_surface_create(hdc);
	cairo_t *         cr  = cairo_create(crs);

	cairo_select_font_face(cr, <span class="o">"Arial"</span>, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size(cr, <span class="o">12.0</span>);
	cairo_move_to(cr, <span class="o">10.0</span>, <span class="o">10.0</span>);
	cairo_show_text(cr, <span class="o">"Hello world"</span>);
	cairo_destroy(cr);
	cairo_surface_destroy(crs);

	<span class="k">return</span> <span class="o">1</span>;
}</pre>

<p>Those examples are a little bit rough, but usually enough to get you started.</p>

<h3>Memory management</h3>

<p>Like most of the API of this library, memory management has been carefully
written to avoid dealing directly with this cruft. There is two kinds of resource
you might have to free manually: graphic contexts and fonts.</p>

<p>With fonts, the recommended way to deal with them, is to store them in a
global list, or preopen them at startup, since it is not require to have a
graphic context to open them. Then, when you want to use a different font
in a graphics context, simply use <tt>GFX_SetFont()</tt>, and be done with it.</p>

<p>Graphic contexts need to be freed, only if you alloc them manually, through
<tt>GFX_GetGC()</tt> or <tt>GFX_AllocOffScreen()</tt>. In case the context is
going to be used anytime the application is running (typical for off-screen
bitmap), you don't even have to free it, it will be done automatically when
exiting. The only real need is when calling <tt>GFX_GetGC()</tt> to do draw
directly stuff on a control, usually from a callback that might not provide
a graphic context. Usually, the recommended practive is to invalidate part
of the control you want to redraw using <tt>SIT_Refresh()</tt>, and let the
repainting occuring in the <tt>OnPaint</tt> event. Which you will end up
doing as the stuff you have to draw becomes more and more complex.</p>

<h2 id="clipboard"><span class="num">XIII.</span> Clipboard</h2>

<p>The clipboard is a simple but very convenient mecanism to make
information available to other applications. The typical piece of information is
usually text or image, but can actually be anything you want. You don't
even have to place information in the clipboard, you can do that only
when another application request the content of the clipboard. This
mecanism is known as deferred rendering, and can be useful in case of
the information is costly to produce.</p>

<h3>Managing text</h3>

<p>Before we see how to handle more complex format, let's first check how to
handle one of the most common format usually handled by every applications:
plain text. This library has some functions specifically dedicated to this task:</p>

<dl>
  <dt><tt><span class="t">Bool</span> SIT_CopyToClipboard(SIT_Widget w, <span class="t">STRPTR</span> text);</tt></dt>
  <dd>This simple function will copy the null-terminated string given as parameter and
  place it inside the clipboard, deleting what was previously inside. <tt class="o">True</tt>
  will be returned if the operation completed successfully, <tt class="o">False</tt> otherwise.
  Also, remember to encode your string in UTF-8 charset, you cannot use the default 8bit
  code page or UTF-16 with this interface.
  </dd>

  <dt><tt><span class="t">int</span> SIT_IsFormatAvailable(<span class="t">STRPTR</span> type);</tt></dt>
  <dd>This function will let you know which format is currently available in the clipboard. The
  return value will be <tt class="o">0</tt> if the format is not available or a positive integer
  representing the internal format ID used by the operating system. There are 2 predefined formats:
  <tt>TEXT</tt> and <tt>BITMAP</tt>. Usually the operating system has mecanism to provide text or
  bitmap in multiple formats, this library will try to present them as a single source and use the
  most appropriate format. All the other formats are seen as binary blob.
  
  <p>Alternatively, you can also query the property <tt>SIT_ClipFormats</tt> on the <tt>SIT_APP</tt> widget.
  It will return a <tt class="o">NULL</tt>-terminated array of string (<tt class="t">STRPTR *</tt>)
  representing all the formats currently available.</p></dd>

  <dt><tt><span class="t">APTR</span> SIT_GetFromClipboard(<span class="t">STRPTR</span> type, int * size);</tt></dt>

  <dd>Try to retrieve the specified format from the clipboard. If <tt class="o">"TEXT"</tt> is
  specified for the <tt>type</tt> parameter, the return value will be a NULL-terminated,
  UTF-8-encoded <tt>malloc()</tt>'ed string (that you will have to free yourself).
  <tt class="o">NULL</tt> will be returned if there is no form of text currently in the
  clipboard. <tt>size</tt> is an optional parameter if you want to get the size of the
  memory block allocated (in case of text, it will include the final 0).

  <p>Using <tt class="o">"BITMAP"</tt> as for the <tt>type</tt> parameter, it will try to convert any
  DIB, Bitmap or EMF into a graphics <tt>Image</tt> datatype. You'll have to free this using
  the <tt>GFX_FreeImage()</tt> function (which is NULL-safe).</p>

  <p>Any other format will be retrieved as a binary blob, with no attempts to convert the data.
  This is where the <tt>size</tt> parameter is the most useful. The memory block will have to
  be <tt>free()</tt>'ed by yourself though.</p>
  </dd>
</dl>

<h3>Other formats</h3>

<p>If you want other format than text, or even registering more formats than just text, you will
have to do this in three steps:<p>
<ol>
  <li>Alloc an special memory block for each format you intend to place in the clipboard.</li>
  <li>Fill each memory block.</li>
  <li>Give the ownership of the block to the clipboard</li>
</ol>

<p>This is done by at least three funtions:</p>

<dl>
  <dt><tt><span class="t">APTR</span> SIT_AllocClipboardObject(<span class="t">STRPTR</span> type, ...);</tt></dt>
  <dd>Allocate a shared memory segment to be later placed in the clipboard. Depending on
  <tt>type</tt> parameter, additional arguments are required to allocate the object:
  <ul>
    <li><tt class="o">"BITMAP"</tt>: <tt>type</tt> must be followed by the width, height (in pixels) and the
    depth (in bit per pixel) of the desired bitmap (all parameters will be retrieved as <tt class="t">int</tt>). The returned
    object will be a graphics <tt>Image</tt>, with the bitmap set to 0. You are advised to only change the
    bitmap data and none of the other fields of the <tt>Image</tt> datatype.</li>

    <li><tt class="o">"TEXT"</tt> or <tt class="o">NULL</tt>: memory block returned has to be seen as
    an opaque pointer. Use the function <tt>SIT_AddTextToClipboard()</tt> to fill the block. No other
    arguments are expected after the <tt>type</tt> parameter.</li>

    <li><em>Anything else</em>: the pointer returned is a memory block where you can write whatever
    you want. Another argument is expected following the <tt>type</tt> parameter: the size of the block,
    in bytes. Remember, there is no provision to resize the block after it has been allocated
    (unless you are using <tt>SIT_AddTextToClipboard()</tt>).</li>
  </ul>
  </dd>

  <dt><tt><span class="t">STRPTR</span> SIT_AddTextToClipboard(<span class="t">STRPTR</span> mem, <span class="t">STRPTR</span> text, <span class="t">int</span> sz);</tt></dt>
  <dd>Use this function to fill the memory blob returned by the previous function. Remember to keep
  your text encoded in UTF-8. If the text you want to add is NULL-terminated, you can specify <tt class="o">-1</tt>
  as for the <tt>sz</tt> parameter. The memory block might have to be relocated if enlarged, that's why
  you have to reassign the return value to first parameter.

  <p>This function is efficient enough so that you can write in the block either character per character,
  or whole memory block at once.</p>
  </dd>

  <dt><tt><span class="t">Bool</span> SIT_SetClipboardData(SIT_Widget w, ...);</tt></dt>
  <dd>Once you've finished filling each memory block, you can make them available to the clipboard.
  The vararg part expect a NULL-terminated list of pairs. The first item of the pair must be a
  string describing the format of the 2nd item in the pair (which has to be a pointer allocated
  with <tt>SIT_AllocClipboardObject()</tt>). There is 2 predefined types:
  <ul>
    <li><tt type="o">"TEXT"</tt>: a NULL-terminated, UTF-8 encoded, clipboard alloced string. Do not
    use a malloc()'ed or static string, your program will bite the dust.</li>

    <li><tt type="o">"BITMAP"</tt>: this special type is the only one where you can use non-clipboard
    alloced object. You are allowed to use regular <tt>GFX_CreateImage()</tt> or <tt><a href="#loadbmp">GFX_LoadImage()</a></tt>,
    a copy will be made specifically for the clipboard. If you used <tt>SIT_AllocClipboardObject()</tt>,
    the image will become the property of clipboard.</li>
  </ul>

  <p>Any other string, will expect a memory block allocated by <tt>SIT_AllocClipboardObject()</tt> and
  be transmitted as is, to the clipboard. A very typical name for the format is to use mime/type
  declaration like <tt class="o">"text/html"</tt> for HTML, <tt class="o">"image/png"</tt> for
  compressed bitmap, ...</p>

  <p>Upon transmission of your block to the clipboard, the memory block will then be property of the
  clipboard. <strong>You won't have to manage the life cycle of objects past this function call</strong>.
  In fact, in all clipboard related API, there is no function to explicitely free a memory block
  returned by <tt>SIT_AllocClipboardObject()</tt>. In the unlikely case you get a NULL pointer
  from the previous function and have already allocated some other memory blocks, it is advised to
  still transmit what you already have to the clipboard.</p>

  </dd>
</dl>

<h3>Clipboard notification</h3>

<p>It is possible to be notified within top-level dialog, whenever the content of the clipboard changes.
This can be useful when dealing with toolbar to disable paste button and the like in case of the content
of the clipboard does not match what the application expect. To do this, there is a dedicated event type:
<tt>SITE_OnClipChanged</tt>, usually setup on the dialog. The <tt>call_data</tt> parameter will be always
set to <tt class="o">NULL</tt>. To know what format is currently available, read the property
<tt>SIT_ClipFormats</tt> on your <tt>SIT_APP</tt> widget (the type stored in this property is
<tt><span class="t">STRPTR</span> *</tt>: <tt class="o">NULL</tt>-terminated array of string).</p>

<p>Usually to enable/disable menu items related to clipboard, it is best to do this in the
<tt>SITE_OnInitMenu</tt> event.</p>

<h3>Deferred rendering</h3>

<p>When an application is working with large or complex memory blocks, it might be useful to defer the generation
of these blocks up to the moment they really are requested. For example when dealing with large bitmap,
you might want to compress it to PNG or JPEG before. Doing this every time a cut/copy operation is done
might induce some significant lag within the application itself. It is hopefully possible to avoid this
costly step and only do it when an application request the block, with the added benefit that the lag
will now be the problem of the requesting application (it is possible to detect if pasting involve
the same application and short-circuit the whole clipboard in this case).</p>

<p>To enable deferred rendering, the only thing to do is to transmit <tt class="o">NULL</tt> as for the
memory blocks sent to <tt>SIT_SetClipboardData()</tt>. This is where the widget parameter of this
function comes into play: when it is time to generate the blocks, a notification will be sent to this
widget. The event type will be <tt>SITE_OnClipRender</tt>. The <tt>call_data</tt> for this parameter
will be the format (<tt class="t">STRPTR</tt>) requested by the application. Only one format at a time
will be requested.</p>

<p>Then proceed as described before: alloc an object through <tt>SIT_AllocClipboardObject()</tt> and
transfers it to the clipboard using <tt>SIT_SetClipboardData()</tt> (this time of course, you cannot
sent <tt class="o">NULL</tt> as for the memory block). You'll have to transfert the format one at a
time.</p>

<p>Also when your application is about to exit, while you still have deferred rendering formats in the
clipboard, the operating system will ask your application to generate each of them at this moment.
Just don't be surprised to see some unusual callbacks being triggered this late.</p>

<h2><span class="num">XIV.</span> Internationalization</h2>

<p>Internationalization refers to everything required for an application
to <em>speak</em> in a different language than the one it was originally
written for. This includes lots of concepts, like date and number formatting,
currency, left-to-right or right-to-left writtings, input methods, and
of course, messages displayed by your application. For the sake of
simplicity, we will only explain the latter point: translating messages
of your application.</p>

<p>The UtilityLib library that SIT is built upon, provides a simpler way to
manage internationalization than the recommended method from Microsoft
(namely using string resources tagged with country code). Using string
resource will require you to manage a list of separate ID, that you'll
need to use in place of your actual message. Having been there and done
that, it is by far not the easiest way to handle this problem.</p>

<p>Instead, the UtilityLib uses a method similar to the <tt>gettext()</tt>
interface, but with some simplifications. You can read an extensive
documentation of gettext on
<a href="http://www.gnu.org/software/gettext/manual/gettext.html">FSF website</a>,
especially chapters 1, 3, 4 and 11.</p>

<p>To quickly sum up: <tt>gettext</tt> acts as a dictionnary, but instead of
words, it will be entire sentences (messages) from your program. The core of
the API is composed of one function: <tt>char * gettext(char * msg);</tt>.
You give it one message and it returns the translated version using the current
locale (or in case of the UtilityLib, the catalog you loaded prior to translate
any message). If the translation was not found, it will simply return the first
argument you provided. So without further action, gettext act as a light-weight
no-op.</p>

<h3>Locale information</h3>

<p>Before to be able to translate anything, you'll first need to know what
is the current language of the operating system your application is on. You
can always later provide a menu to let the user select its own language, but
the first time the application is launched, it is advised to use the preferred
language. Also take note that changing messages of an application after it
has started is usually way too much work, not really worth the effort.</p>

<p>The locale information is actually stored in the <tt>SIT_App</tt> widget,
into the property <tt>SIT_LocaleInfo</tt>. The content of this property is a
pointer to a <tt>LocaleInfo</tt> structure. You can find its definition in
the main header <tt>SIT.h</tt>:</p>

<pre><span class="t">struct</span> LocaleInfo_t        <span class="c">// Example:</span>
{
    STRPTR nlsLang;        <span class="c">// Fran&ccedil;ais</span>
    STRPTR nlsCountry;     <span class="c">// France</span>
    STRPTR engLang;        <span class="c">// French</span>
    STRPTR engCountry;     <span class="c">// France</span>
    STRPTR iso3166;        <span class="c">// FR_fr</span>
    STRPTR currency;       <span class="c">// &euro;</span>
    STRPTR currencyName;   <span class="c">// Euro</span>
    STRPTR currencyCode;   <span class="c">// EUR</span>
    STRPTR shortDate;      <span class="c">// dd/MM/yyyy</span>
    STRPTR longDate;       <span class="c">// dddd d MMMM yyyy</span>
    STRPTR decimalSep;     <span class="c">// ,</span>
    STRPTR months[<span class="o">12</span>];     <span class="c">// janvier, f&eacute;vrier, ...</span>
    STRPTR abbrMonths[<span class="o">12</span>]; <span class="c">// janv., f&eacute;vr., ...</span>
    STRPTR weekDays[<span class="o">7</span>];    <span class="c">// lundi, mardi, ...</span>
    STRPTR abbrWeek[<span class="o">7</span>];    <span class="c">// lun., mar., mer., ...</span>
    STRPTR langCode;       <span class="c">// 040C</span>
    STRPTR intlPrefix;     <span class="c">// 33</span>
};
</pre>

<p>This structure is particularly important to know how to uniquely get the
name of the language, in order to name your language file accordingly. In this
case, it is advised to use the ISO 3166 country code, since it guaranteed to be
unique and only use ASCII charset. The other fields might contain unicode
characters.</p>

<h3 id="msgextract">Automating message extraction</h3>

<p>Maintaining multiple translation files is usually a tedious process, so it
better has to be automated as much as possible. The first step into translating
an application is to prepare the messages of your program as described in
<a href="http://www.gnu.org/software/gettext/manual/gettext.html#Preparing-Strings">section
4.3: Preparing Translatable Strings</a>.</p>

<p>The only difference is that the function to extract a message from the
catalog is named <tt>LangStr()</tt> instead of <tt>gettext()</tt>, and both are
usually abridged <tt>_()</tt> to limit the overhead of translation.</p>

<p>For example, to translate the Hello world program given in
<a href="#chapter4">chapter IV: Getting Started</a>, you only have to
modify the label creation, with the following line:</p>

<pre>SIT_CreateWidget(_(<span class="o">"hello, world"</span>), SIT_LABEL, dialog, <span class="o">NULL</span>);</pre>

<p>You'll have to mark all of your message that way. Once it is done, you
can use the <tt>msgextract</tt> utility to extract them in one shot, and
update/create every translation file. You can find it in the <tt>Tools</tt>
folder of the SIT distribution. The way this utility works is through an INI
configuration file. A typical configuration for extracting messages from C
source files is:</p>

<pre><span class="t">Lang</span>=lang
<span class="s">[1]</span>
<span class="t">Folder</span>=*.c
<span class="t">Prefix</span>=_("
<span class="t">Suffix</span>=<span class="o">"<span class="s">\"</span>)"</span></pre>

<p>The following keywords can be specified:</p>
<ul>
  <li><tt>Lang</tt>: must the first keyword of this file. Indicate where
  catalog (dictionnary) files will be updated.</li>
  <li><tt>Folder</tt>: an optional path followed by a MS-DOS wildcard, use to filter
  files to be scanned for messages to be extracted and merged with language
  files.</li>
  <li><tt>Prefix</tt>: the starting string that mark the beginning of a
  message to extract.</li>
  <li><tt>Suffix</tt>: the string that mark the end of the message.</li>
</ul>

<p>If your configuration was named "<tt>msgextract.ini</tt>", you can then
simply initiate message extraction with the following commands (otherwise
you'll have to provide the configuration file as the first argument):</p>

<pre><span class="c">C:\Project\HelloWorld&gt;</span>mkdir lang

<span class="c">C:\Project\HelloWorld&gt;</span>touch lang\FR_fr.po

<span class="c">C:\Project\HelloWorld&gt;</span>msgextract
parsing .\Hello.c...
1 file processed for message translation.
FR_fr.po updated: 1 added, 0 commented, 0 untouched.

<span class="c">C:\Project\HelloWorld&gt;</span>
</pre>

<p>The way <tt>msgextract</tt> works is to extract every strings from each
folder directive of every section within the configuration file (in case
your application is spread over multiple directories). It will
then load each catalog from the <tt class="t">Lang</tt> folder, and add
messages that are missing in catalog and comment those are no more
referenced. That's why we created an empty language file before starting
the extraction. The resulting file <tt>lang\FR_fr.po</tt> looks like:</p>

<pre><span class="c"># NEW MESSAGES</span>
<span class="k">msgid</span> <span class="o">"hello, world"</span>
<span class="k">msgstr</span> <span class="o">""</span></pre>

<p>Which is basically empty. You'll now have to fill every <tt class="k">msgstr</tt>
directive that have an empty string associated (remember to have your file
encoded in UTF-8). Here we choose to use the ISO 3166 code for french, so a
possible translation would be:</p>

<pre><span class="k">msgid</span> <span class="o">"hello, world"</span>
<span class="k">msgstr</span> <span class="o">"bonjour, tout le monde"</span></pre>

<p>For the <tt>LangStr()</tt> function, an empty string is the same as a
missing string: the original pointer you provided will be returned in
that case. Once this language file has been filled, you can then load
it at the beginning of the application (or at least, before calling
the <tt>LangStr()</tt> function).</p>

<p>Note that PO files parsed by the <tt>UtilityLib</tt> provide an
extension: it allows you to include another translation file through the
<tt>#include</tt> directive. This directive must be followed by the path
of the file, without quote, relatively to language file where the
directive is in. A over-typical application for this is to have
catalogs for countries with the same basic language, but with small
variations, like british english versus american english, or
french versus canadian french, etc...</p>

<h3>Loading translation file</h3>

<p>Once your language file is done, you can load it. Here, there is a little
simplification compared to the original <tt>gettext()</tt>: <tt>gettext</tt>
package handle two file formats: the portable object format
(PO: the one you edit to translate your messages) and the machine object
(MO: the one loaded by your application), which is a compiled form of the PO
file. The utility library can actually load PO files directly, there is no
need for MO files at all. This is done through this function:</p>

<pre>Lang LangParse(STRPTR path);</pre>

<p>The path (UTF-8 encoded) will have to be built using the locale information
from the <tt>SIT_APP</tt> widget and the convention you use earlier to create
your translation file. Since we use the ISO 3166 code, the hello world
application can now be updated that way to include full support for
internationalization:</p>

<pre><span class="d">#include</span> <span class="o">&lt;SIT.h&gt;</span>

<span class="t">int</span> my_main(<span class="t">int</span> nb, <span class="t">char</span> * argv[])
{
	SIT_Widget app = SIT_CreateWidget(<span class="o">"HelloWorld"</span>, SIT_APP, <span class="o">NULL</span>, <span class="o">NULL</span>);
	LocaleInfo info;
	TEXT path[<span class="o">32</span>];

	SIT_GetValues(app, SIT_LocaleInfo, &amp;info, <span class="o">NULL</span>);
	sprinf(path, <span class="o">"lang/<span class="s">%s</span>.po"</span>, info-&gt;iso3166);
	LangParse(path);

	SIT_Widget dialog = SIT_CreateWidget(<span class="o">"Hello"</span>, SIT_DIALOG, app,
		SIT_Font,    <span class="o">"System/30"</span>,
		SIT_Margins, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>, <span class="o">10</span>,
		<span class="o">NULL</span>
	);
	SIT_CreateWidget(_(<span class="o">"hello, world"</span>), SIT_LABEL, dialog, <span class="o">NULL</span>);
	SIT_ManageWidget(dialog);

	<span class="k">return</span> SIT_Main();
}</pre>

<p>In that case, we don't care about the return code of <tt>LangParse</tt>,
because if it succeeds, the <tt>UtilityLib</tt> will keep a reference, and
if it fails, all function call to <tt>LangStr()</tt> will return the 
first argument. We used the abridged form of this function in the example
above: the <tt>_</tt> function is defined like this:</p>

<pre>#define _(str)              LangStr(NULL, str)</pre>

<p>Also note that the <tt>LangParse()</tt> can only read regular files, not resources or
inline blob like <tt>GFX_LoadImage()</tt>.</p>

<h3>Advanced features</h3>

<p>There are a few more features to be aware in order to be to able to handle
real world applications.</p>

<h4>Dummy strings</h4>

<p>When writing an application, it often arrives that a few static tables are
declared in the global scope, that contains some strings that you want to be
translated. A typical example would be menu structure:</p>

<pre><span class="t">static</span> SIT_MenuStruct menu[] =
{
    {<span class="o">1</span>, <span class="o">"&amp;Game"</span>},
        {<span class="o">2</span>, <span class="o">"&amp;Start"</span>,    <span class="o">"N"</span>, <span class="o">0</span>, <span class="o">101</span>},
        {<span class="o">2</span>, <span class="o">"S&amp;ettings"</span>},
            {<span class="o">3</span>, <span class="o">"Easy"</span>,      <span class="o">NULL</span>, SITM_Toggle(<span class="o">103</span>) | SITM_Checked, <span class="o">102</span>},
            {<span class="o">3</span>, <span class="o">"Normal"</span>,    <span class="o">NULL</span>, SITM_Toggle(<span class="o">104</span>), <span class="o">103</span>},
            {<span class="o">3</span>, <span class="o">"Expert"</span>,    <span class="o">NULL</span>, SITM_Toggle(<span class="o">105</span>), <span class="o">104</span>},
            {<span class="o">3</span>, <span class="o">"Custom..."</span>, <span class="o">"C"</span>, <span class="o">0</span>, <span class="o">105</span>},
        {<span class="o">2</span>, <span class="o">"&amp;Auto discover"</span>},
            {<span class="o">3</span>, <span class="o">"Empty cells only"</span>, <span class="o">NULL</span>, SITM_Toggle(<span class="o">1081</span>), <span class="o">1080</span>},
            {<span class="o">3</span>, <span class="o">"Obvious flags"</span>,    <span class="o">NULL</span>, SITM_Checked, <span class="o">1081</span>},
        {<span class="o">2</span>, <span class="o">"S&amp;cores..."</span>, <span class="o">"H"</span>, SITM_Disabled, <span class="o">106</span>},
        {<span class="o">2</span>, SITM_SEPARATOR},
        {<span class="o">2</span>, <span class="o">"E&amp;xit"</span>,     <span class="o">"Q"</span>,  <span class="o">0</span>, <span class="o">107</span>},
    {<span class="o">0</span>}
};</pre>

<p>The items of such tables cannot be enclosed by <tt>_()</tt>, in order to
be automatically recognized by the <tt>msgextract</tt> tool. To still allow
this tool to extract all messages to be translated, there is a special macro
that actually does nothing but permits the <tt>msgextract</tt> tool to do its
work:</p>

<pre><span class="s">#define	D_(str)             str</span></pre>

<p>Since a typical configuration for <tt>msgextract</tt> is to extract
everything between <tt>_("</tt> and <tt>")</tt>, this simple macro does the
job. However, your structure won't be translated: after reading your language
file, you'll have to manually modify each field that got marked. You usually
only have to do this at startup. For menu structure, like the one above, you
can use the following code:</p>

<pre><span class="k">for</span> (i = <span class="o">0</span>; menu[i].level; i ++)
	menu[i].label = _(menu[i].label);</pre>

<p>Remember that despite we used the abridged version of <tt>LangStr()</tt>, it
won't be recognized by the <tt>msgextract</tt> utility, because it has been
configured to extract everything between <tt>_("</tt> and <tt>")</tt>. You
might also notice that since we are overwritting the global structure, this
type of construct does not allow changing the language at runtime.</p>

<h4>Handling plural form</h4>

<p>Plural usually involve displaying a quantified noun, while trying to have
a grammatically correct sentence for every possible values. Back in the days
nobody gave a damn about plural form, you got something along the line:
<tt>"%d file(s) processed"</tt> for every values of <tt>%d</tt>, and usually
something even worse for other languages. If you want to display something
more user-friendly, a little bit of work is needed.</p>

<p>We used to dintinguish 3 cases for handling plural form: no quantity,
singular and plural. Each of these cases mean they will have a dedicated
message. If the quantity to display is zero, it might be wise to consider
removing the message completely if the message does not have any value.
For example if you want to display some information on selected items
and if there is nothing selected, just don't display anything. On the
other way, if this message is the result of a lengthy operation, it might
still be interesting to display it, just to signal to the user that
something has been done, but there is no results to display.</p>

<p>Also don't try to programmatically build sentences to accomodate plural
form, like this:</p>

<pre>fprintf(<span class="o">stderr</span>, <span class="o">"<span class="s">%d</span> file<span class="s">%s</span> processed.<span class="s">\n</span>"</span>, n, n == <span class="o">1</span> ? <span class="o">""</span> : <span class="o">"s"</span>);</pre>

<p>This is impossible to translate properly, since most languages have a
more complex plural form than that, where more than one word can be
impacted.</p>

<p>The function to deal with plural is declared like this:</p>

<pre><span class="t">STRPTR</span> LangStrPlural(Lang lang, <span class="t">int</span> nb, <span class="t">STRPTR</span> sing, <span class="t">STRPTR</span> plur);</pre>

<p>And is usually abridged the following way:</p>

<pre><span class="s">#define	_N(n, sing, plur)   LangStrPlural(<span class="o">NULL</span>, n, sing, plur)</span></pre>

<p>If you used literal strings as arguments to this function, you will notice
that they will not be recognized by <tt>msgextract</tt> utility. You'll have
to enclose them with a dummy declaration. Take also note that no quantity
case is not handled by this function, you'll have to add special processing
if you ever plan to handle that case.</p>

<h2><span class="num">XV.</span> Multi-thread</h2>

<p>This part will briefly explain why and when to use multi-thread programming
within your applications. Multi-thread is actually pretty simple, but since
there is so many pitfalls, you can shoot yourself in your feet faster you
can think about it. An extremely cautious behavior is advised when venturing
in this area, because errors that can arise from a misbehaved thread can drive
you mad.</p>

<p>First, graphical interface and multi-thread does not mix very well. This
library is no exception, since 99% of all functions <strong>are not thread
safe</strong>. That means you <strong>cannot</strong> manage the event within
one thread and paint the scanlines of a bitmap resulting of a lengthy computation
into another thread. You'll have to add some synchronization in between. This
is usually done in a few lines of code, but once again, failure to do so,
can result in strange behavior, including crash in portion of the program that
are completely unrelated to the actual problem.</p>

<p>Usually, you let the main thread handle the interface, and then start
another thread if needed. The rule of the thumb is, if a process is going to
take more than 5 to 10 seconds, it might be wise to delegate the work to a
background thread, while the main interface is monitoring the progress.
If the process is over one minute, it is not that overkill to also include
a button to cancel the operation. Remember, if you let the main thread handle
everything, the interface will be completely unresponsive to any event (like
repainting, moving, resizing, ...), which is very annoying to a user
stand-point.</p>

<p>Still, not every process can be splitted into discreet steps, but at
least provide some feedback that something is going on. If the loop is
computationally intensive, the notification is more than advised, because on
some devices, this might spin the cooling fans and induce quite some noise.
Some operations might be inherently slow, with no way to multiplex them with
the main message loop. A very common case is network name resolution (DNS),
using function from winsock API like <tt>gethostbyname()</tt>: you'll have
to use a worker thread and notify the interface when the operation is done.</p>

<p>Once again, explaining best practice for thread management is out of the
scope of this document, if it is your first time you heard about thread, you
should consider reading another source before, like:</p>

<ul>
  <li><a href="http://en.wikipedia.org/wiki/Thread_%28computer_science%29">Thread: introduction</a></li>
  <li><a href="http://en.wikipedia.org/wiki/Critical_section">Critical section</a></li>
  <li><a href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29">Semaphores</a></li>
</ul>

<p>The <tt>UtilityLib</tt> library will provide most of the functions to deal
with thread. <tt>SIT</tt> contains only one function to provide a link with the
interface:</p>

<dl>
  <dt><tt>Thread ThreadCreate(ThreadCb func, APTR arg);</tt></dt>
  <dd>This is used to start a new thread. <tt>func</tt> is the function to run
  in parallel (using standard <tt>cdecl</tt> calling convention) and <tt>arg</tt>
  will be given as first argument to your function.</dd>

  <dt><tt><span class="t">void</span> SIT_Notify(SIT_Widget, APTR data);</tt></dt>
  <dd>Has been briefly mentionned in the <a href="#">chapter VII: Event</a>. This
  function will trigger an <tt>OnUser</tt> event on the widget specified as the
  first argument. <tt>data</tt> will be available through the <tt>call_data</tt>
  parameter (second parameter) of the callback (not to be confused with user data
  parameter). This function is guaranteed to be thread-safe.</dd>

  <dt><tt><span class="t">void</span> ThreadPause(<span class="t">int</span> delay);</tt></dt>
  <dd>It will put the calling thread into a graceful sleeping mode (ie: will
  not hog the CPU). <tt>delay</tt> specify how many milisecond to sleep. Do not
  expect to be a high precision timer though, the best you can hope is around
  10ms. If you want less, you'll have to use an active loop or a combination
  between the two.</dd>

  <dt><tt>Mutex*</tt></dt>
  <dd>This class of functions is useful if you want to access to a shared resource.
  It is implemented as a critical section. This is the basic object for
  synchronizing threads.</dd>

  <dt><tt>Sem*</tt></dt>
  <dd>Usually targetted for producer/consumer model, this group of functions
  will let you manage semaphore object. Strictly speaking, a semaphore can be
  implemented using an integer and two mutexes. The exercise will be left for
  the reader.</dd>
</dl>

<h2 id="chapter16"><span class="num">XVI.</span> Resources</h2>

<p>Resources are a way to store additionnal files and/or information within
your main executable, so that from a user stand point, your program is seen
as a single file. This is a Microsoft Windows specificity, and the way to indicate
which files will be contained in your program depends on your development
environment, so we'll assume the lowest common denominator in this section:
command line and text editor. Still, check out your development tools for
something more productive.</p>

<p>Storing additionnal files can be useful if those files are critical or even
just useful for running your program. It is not mandatory to include them, but
it is part of what makes an application looks polished. This can include:</p>
<ul>
  <li>Bitmaps used by controls.</li>
  <li>Manifest for using common controls library v6 or later.</li>
  <li>Icon of your application (this is even mandatory if you want it displayed
  by the explorer).</li>
  <li>Version/vendor information (which can be read by external tools).</li>
  <li>Any binary blob you might deemed necessary...</li>
</ul>

<p>Keep in mind that those resources are <strong>read only</strong>, if
you want to modify a file, you'll have to make it external. Also, when
starting an application, resources will only be loaded on demand. This
is the most obvious advantage compared to using inline resources (like
a stringified binary blob): inline resources will make your application
use more memory and be slower to start, whether you use the resource
or not. Don't start to freak out though, by putting everything into
resource just to save a few hundreeds of bytes. Small bitmaps like
toolbar icons won't make any difference, unless you have hundreeds of
them, giant animated 32bpp images used to display your overly-kitch
about box certainly will.</p>

<p>The way resources work is to create a text file (.rc) where you give a link
to external files or put information inline, then you use an external tool
(<tt>RC.EXE</tt> using Microsoft toolchain, <tt>windres.exe</tt> using
GNU tools, ...) to produce a linkable object (it usually has a <tt>.res</tt>
extension), that you can include in the list of objects to produce your final
application. So, the starting point is writing this text file.</p>

<h3 id="resfmt">Resource compiler file</h3>

<p>The resource compiler (RC) file specification can be read from the
<a href="http://msdn.microsoft.com/en-us/library/aa380599%28VS.85%29.aspx">MSDN</a>
web site, for the sake of conciseness, we'll focus on a few key points that are
used in almost every programs.</p>

<p>This file bears some similarity with a C program, since resource compilers
will usually pre-process this file using the default C pre-processor. That
means you can <tt>#include</tt> any header file and use their <tt>#define</tt>s,
or even define your own constants and use them in place of numeric/string
litterals.</p>

<p>Resources are declared one after the other, and usually start by two tokens:
the first is its ID (which can be an integer or an arbitrary string), followed
by the type of the resource (which can be a symbolic name or an integer). The
uniqueness of the resource is identified by the pair (ID, type): you can have
the same ID for different types. After the type, you describe the resource
itself (either by giving a link to an external file or putting information
inline). We'll describe a few resource types, for a complete list you'll have
to check MSDN website.</p>

<dl>
  <dt><tt>ICON</tt></dt>
  <dd>This directive let you link an external icon (ICO format) with your program.
  It is useful if you want to give a customized icon to be displayed by external
  tools, like file explorers or want to use customized icon for your dialogs. For example:
  <pre>1 <span class="c">ICON</span> "MyApplication.ico"</pre>
  <p>The lowest ID will be used to display the icon of your application.</p>
  </dd>

  <dt><tt>BITMAP</tt></dt>
  <dd>Similar to ICON, it allows you to include an external image. The only caveat
  is that it has to use the BMP format. No PNG or JPEG allowed. For example:
  <pre>1 <span class="c">BITMAP</span> "MyImage.bmp"</pre>
  This resource can then be loaded using <tt><a href="#loadbmp">GFX_LoadImage()</a></tt> function.</dd>

  <dt><tt>MANIFEST</tt> (24)</dt>
  <dd>Starting with Windows XP, Microsoft introduced a new mecanism to deal with
  what was known by that time as DLL Hell: applications that relied on two different
  versions of the same library (with the same name). Moreover, it was not always
  possible to copy that library in the application folder, because this DLL was
  often among the system libraries (msvcrt, comctl, ...).

  <p>Instead of only having the latest version of a given DLL, this mecanism allowed
  to keep a copy of all minor release that some applications may rely upon. It is
  known as the Windows side by side registry, or WinSxS. Every DLL registered in it
  must be explicitely stated in a manifest file, otherwise Windows will revert back
  to the old school loading mecanism. The most well known DLL using this mecanism
  is the common control library, the one that handle the look'n feel of your
  application. Starting with version 6, you must explicitely state that you want
  this version or later, otherwise the system will load the v5
  or older (since there is significantly differences between v6 and older versions),
  giving to your application that Windows 95 era look and feel.</p>
  
  <p>To do this, you'll have to write an XML file, that look something like:</p>

  <pre><span class="c">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;</span>
<span class="i">&lt;assembly <span class="t">xmlns</span>=<span class="o">"urn:schemas-microsoft-com:asm.v1"</span> <span class="t">manifestVersion</span>=<span class="o">"1.0"</span>&gt;</span>
&nbsp;&nbsp;<span class="i">&lt;assemblyIdentity <span class="t">name</span>=<span class="o">"MyApplication"</span> <span class="t">processorArchitecture</span>=<span class="t">"*"</span> <span class="t">version</span>=<span class="o">"1.0.0.0"</span> <span class="t">type</span>=<span class="o">"win32"</span>/&gt;</span>
&nbsp;&nbsp;<span class="i">&lt;description&gt;</span>MyApplication<span class="i">&lt;/description&gt;</span>
&nbsp;&nbsp;<span class="i">&lt;dependency&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;dependentAssembly&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;assemblyIdentity <span class="t">type</span>=<span class="o">"win32"</span> <span class="t">name</span>=<span class="o">"Microsoft.Windows.Common-Controls"</span> <span class="t">version</span>=<span class="o">"6.0.0.0"</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="t">processorArchitecture</span>=<span class="o">"*"</span> <span class="t">publicKeyToken</span>=<span class="o">"6595b64144ccf1df"</span> <span class="t">language</span>=<span class="o">"*"</span>/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dependentAssembly&gt;
&nbsp;&nbsp;&lt;/dependency&gt;
&lt;/assembly&gt;</span></pre>
  Replace "<tt>MyApplication</tt>" by whatever you want, or leave it as is,
  since it doesn't matter that much: unless your users start hex-editing your
  binary, they won't see that message. If
  you save that file using the same name as your application, but with a
  "<tt>.manifest</tt>" extension appended, this file will automatically be read
  by the operating system. If you want to include that file with your program,
  you can use a <tt>MANIFEST</tt> section like this:
  <pre>1 <span class="c">MANIFEST</span> "MyApplication.exe.manifest"</pre>
  Take note that the manifest file takes precedence over the manifest declared
  as resource.</dd>

  <dt><tt>VERSIONINFO</tt></dt>
  <dd>This node will give some extra information for external tools, to know
  your application's version, author, copyright, company, ... Its syntax is a
  little bit weird, but a typical template looks like:
  <pre>1 <span class="c">VERSIONINFO</span>
<span class="t">FILEVERSION</span> <span class="o">3</span>,<span class="o">141</span>,<span class="o">592</span>,<span class="o">653</span>
<span class="t">PRODUCTVERSION</span> <span class="o">2</span>,<span class="o">718</span>,<span class="o">281</span>,<span class="o">828</span>
<span class="t">FILETYPE</span> VFT_APP
{
    <span class="k">BLOCK</span> <span class="o">"StringFileInfo"</span>
    {
        <span class="k">BLOCK</span> <span class="o">"040904b0"</span>
        {
            <span class="k">VALUE</span> <span class="o">"CompanyName"</span>,      <span class="o">"MyCompany Inc."</span>
            <span class="k">VALUE</span> <span class="o">"FileVersion"</span>,      <span class="o">"3.141592653"</span>
            <span class="k">VALUE</span> <span class="o">"FileDescription"</span>,  <span class="o">"My awesome application."</span>
            <span class="k">VALUE</span> <span class="o">"InternalName"</span>,     <span class="o">"MyApp"</span>
            <span class="k">VALUE</span> <span class="o">"LegalCopyright"</span>,   <span class="o">"<span class="s">\xa9</span> Me"</span>
            <span class="k">VALUE</span> <span class="o">"LegalTrademarks"</span>,  <span class="o">"AYBABTU"</span>
            <span class="k">VALUE</span> <span class="o">"OriginalFilename"</span>, <span class="o">"MyApplication.exe"</span>
            <span class="k">VALUE</span> <span class="o">"ProductName"</span>,      <span class="o">"MyApplication"</span>
            <span class="k">VALUE</span> <span class="o">"ProductVersion"</span>,   <span class="o">"3.14"</span>
        }
    }
    <span class="k">BLOCK</span> <span class="o">"VarFileInfo"</span>
    {
        <span class="k">VALUE</span> <span class="o">"Translation"</span>, <span class="o">0x0409</span>, <span class="o">1200</span>
    }
}</pre>

  <p><tt class="t">FILEVERSION</tt> at the beginning of the block will define the
  master version of your application and will be displayed by tools like
  process explorer or version tab of properties panel of Windows explorer. This
  is a comma-separated list of four 16bit unsigned integers.
  <tt class="t">PRODUCTVERSION</tt> is usually not displayed by many tools,
  although it uses the same syntax than <tt>FILEVERSION</tt>.</p>

  <p>After that you have two blocks used in conjunction: <tt>StringFileInfo</tt>
  and <tt>VarFileInfo</tt>. The idea behind these blocks is to allow you to
  specify multiple translations for the version information. Unfortunately, the
  Windows explorer will only display the first one, and does not even choose
  the one that best match the user operating system locale.</p>

  <p>So most application only provides an english version, identified by the
  language code 0x0409, with 1200 (or 0x04b0 in hex) being the charset ID.
  Back in the days where only 8bit charsets existed, this parameter might had
  some importance, nowadays, since everything is stored using UTF-16 encoding,
  it does not matter that much.</p>

  <p>So with the combination of the language code and charset ID described in
  the <tt>VarFileInfo</tt>, you can declare a dedicated section in the
  <tt>StringFileInfo</tt> block, where you enumerate the fields.</p>

  <p>To make this long story shorter: copy and paste the above template and
  replace each entries in the <tt>StringFileInfo</tt> block with whatever
  describe the best your application.</p>

  </dd>
  
  <dt>Binary file</dt>
  <dd>You can include any arbitrary files with your application. <tt><a href="#loadbmp">GFX_LoadImage()</a></tt>
  will allow you to get any image type from these resources (PNG, BMP, JPEG). If you want
  to read these resources yourself, you'll have to use Win32 API directly though.

  <pre>1 <span class="c"><em>typeID</em></span> "path\\to\\filename"</pre>

  <p>Where <em>typeID</em> is an integer greater than 255.</p>

  </dd>

</dl>

<h3>Handling unicode</h3>

<p>Resource messages are stored in unicode (or more precisely using UTF-16
encoding), that means every string (double-quoted literals) can include
unicode characters. It works the same way as C strings: you must declare
a wide-character string by prefixing your literal with a capital <tt>L</tt>.
You can then include unicode characters using the "<tt>\xXXXXXX</tt>"
notation, e.g. <tt class="o"><span class="s">L</span>"\x2122"</tt>
encodes the string <tt class="o">"&trade;"</tt> (trademark symbol).
Without that <tt>L</tt>, you'll get the string <tt class="o">"!22"</tt>.</p>

<p>The only caveat is when using GNU <tt>windres.exe</tt> tool. It
is included in the <tt>binutils</tt> package and usually installed with
<a href="http://mingw.org/">MinGW</a> or cygwin. Unicode support
has only been added long after Microsoft <tt>RC.EXE</tt> compiler. The
version used for testing was from <tt>binutils</tt> v2.20.51 (July 2010).
If you ever get a "<tt>syntax error</tt>" from <tt>windres</tt> pointing
to a line containing a wide-character string, it is certainly because your
version is not up to date. You can download binary package on the MinGW
website (remember to check for <tt>binutils</tt>, not <tt>windres</tt>).</p>

<h3>Stuff to avoid</h3>

<p>Unless you have a very good reason to do so, here is a brief explanation
of what other resources you can embed, and why you shouldn't do it when
using SIT:</p>

<ul>
  <li><tt class="h">ACCELERATORS</tt>: used to gather menu shortcuts so that
  they can be filtered early from the event loop. They are automatically
  managed for you by SIT using the <tt>SIT_MenuStruct</tt>.</li>

  <li><tt class="h">DIALOG</tt> and <tt class="h">DIALOGEX</tt>: allows you to
  describe a complete dialog, along with their controls, and then create the
  window in one API call. Sounds nice, except there is no layout manager. You
  can have the same features and more using the <tt>SIT_CreateWidgets()</tt>
  and <tt>SIT_SetAttributes()</tt> functions.</li>

  <li><tt class="h">MENU</tt>, <tt class="h">MENUEX</tt> and <tt class="h">POPUP</tt>:
  like with <tt>DIALOG</tt> and <tt>DIALOGEX</tt>, those directives allow you to
  store complete menus that can be created in one API call. <tt>SIT_MenuStruct</tt>
  provides the same features.</li>

  <li><tt class="h">MESSAGETABLE</tt> and <tt class="h">STRINGTABLE</tt>:
  Microsoft recommended way to handle internationalization. Read the dedicated
  chapter to remember why it's a bad idea. Short version: use external files
  with a <tt>gettext()</tt>-like interface.</li>
</ul>

<p>This list is not exhaustive however, check MSDN web site for a complete
reference of what can be included.</p>

<h3>Compiling</h3>

<p>Once you've written your <tt>RC</tt> file, it's time to compile it, just like
you would with a C/C++ file. For example a typical command line when using GNU
<tt>windres.exe</tt> would be:</p>

<pre>C:\Projects\MyApp&gt;windres.exe -i MyApplication.RC -J rc -o MyApp.res -O coff -IC:\MinGW\include</pre>

<p>This will produce a <tt>MyApp.res</tt> that you must include in the list of
object files to produce your application. We won't show you how to do it using
Microsoft's <tt>RC.EXE</tt>, because nobody is doing it that way.</p>

<p>So it is strongly encouraged to look for some helper in your integrated
development environment. For example in Code::Blocks, the only thing to do
once your <tt>RC</tt> has been written is to include it in your project, just
like a standard C/C++ file. It will then take care of the rest for you: update
list of object files to link, automatically regenerate your <tt>.res</tt> file,
whenever you modify the corresponding <tt>.rc</tt> file and use the right tool
(windres.exe, RC.exe, ...) to compile your file.</p>

<h2 id="chapter17"><span class="num">XVII.</span> Utility tools</h2>

<h2><span class="num">XVIII.</span> Guidelines</h2>

<p>This section is intended to show you some recommended practice for building
user interface. There are infinite ways to build user interface, but as you'll
quickly find out, most of them will lead you to dead-end or very disappointing
results. This is where guidelines can become handy: it will present you a set of
reasons as to why interface should be built in certain ways, so that you can get
effective results with minimal effort. Also, do not make the mistake to mismatch
guidelines with standard. Guidelines are intended to be broken if you can come
up with more compeling reasons than what is described here. "Compeling" might
be a little bit subjective and context-dependant, but if you can find at least
one reason that isn't related to the shiny effect or the guru syndrome, it might
be worth doing it (more on this below).</p>

<ul>
  <li>Do not try to owner drawn like crazy. It will make your application
  looks like shit. Use custom draw instead.</li>
</ul>

<h2><span class="num">XIX.</span> Examples</h2>

<p>No library can pretend to be complete, without showing you what real world
applications look like. In the example directory of SIT distribution, you'll
find a couple of these. Since they have been designed with real world usage in
mind, they usually include all that extra code needed to have a polished
application. It usually significantly increase the code size, but at least
they try to show the best practice in handling all the details you usually
found in an application. Extra care have been taken to be sure code remain
clean, efficient, with carefully chosen design patterns, to avoid both
over-engineering and the mess of spaghetti logic.</p>

<h3>XMines</h3>

<img src="images/ExampleXMines.png" style="float: left; margin-right: 5px" alt="XMines screenshot">

<p>An over-classical minesweeper application, that everybody has written at
least once in its lifetime. The purpose is not so much to show you how much
better this version is, compared to the bajillion of other clones, but just to
highlight a few key points, that will come up in almost every applications.</p>

<p>This application is around 1,500 lines of code, and has been rewritten
from scratch, at least 2 times. The first version was a mess, the
second a little bit better but still contained more spaghetti than logic,
the third and final one was something worth showing. This example will
highlight one key point mentionned in <a href="#chapter5">chapter V</a>:
even for what might be considered a trivial application, variables tend to pile
up quickly, and to avoid spreading your logic all over the place, you better
have to gather that into manageable structure. By manageable, try to keep
the code handling that structure around 1,000 lines or less. If you ever
reach that limit, try to see if your logic can be splitted into smaller
chunk.</p>

<p>Other than that, this example will show you basic dialog creation, nothing
really fancy, since most of the code consists into managing the minefield area,
which for sake of laziness has been handled through an offscreen bitmap,
avoiding the need for a custom iterator.
Another point of interest is the handling of replays through a separate
thread: notice how interacting with interface has been carefully limited
to the function <tt>SIT_Notify()</tt>.</p>

<p>Also in the dialog asking for a custom minefield, try to follow the path
of current edit field values, and how they finally got assigned to the game
structure.</p>

<h3 id="giv">GIV</h3>

<p>This one is a full-featured photo viewer loosely inspired by iPhoto on
Mac OS X, with the ability to tag images, and organize them in albums.
Nothing really fancy, but once again, making a polished application usually
requires lots of care in many little details.</p>

<h3 id="sitedit">SITEdit</h3>

<h2><span class="num">XX.</span> Conclusion</h2>

<p>If you read this documentation from the beginning up to here:
congratulations! There may be a few questions you may ask to yourself now:
what does this framework offers that the others don't? Is it really worth
investing some time in it? I feel obliged to answer: not much and no. Among
all the <em>rich</em> client API, if there has to be one that's going to
rule them all, it will be (or already is) the web. It has the easiest 
learning curve, works almost everywhere, has a lot of expressiveness,
highly dynamic, and more importantly, has an extremely active community.
</p>

<p>So what the purpose of all of this? Well, it has already been stated in
the introduction: the current state of framework using plain ANSI C, and
even to some extend C++ is rather poor. Long and steep learning curve
and rather bloat (although extensive) API, come first to mind. </p>


</div>
</div>
</body>
</html>

